- 投稿日:2021-03-22T21:53:51+09:00
dockerコンテナの中でviが使えない場合
- 投稿日:2021-03-22T21:05:47+09:00
docker/docker-composeをAWS AmazonLinux 2にインストール
概要
タイトル通りですが、普段使用しているLinuxと少し違っていたので備忘録として記載します
前提条件
AWS EC2(t2-micro/Amazon Linux2)
Dockerのインストール
yum install でdockerを指定すれば使えるようになります。
$ sudo yum -y update $ sudo yum -y upgrade $ sudo yum -y install dockerdocker-composeのインストール
こっちが少しだけ手こずりました。
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose $ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
- 投稿日:2021-03-22T19:29:05+09:00
【5分でSaaSアプリ作成】スマレジアプリ・スターターパックを公開しました
はじめに
スマレジという非常に多機能なPOS・勤怠管理システム・オーダーシステムを低価格で提供しているタブレットPOSサービスがあるのですが、2020年8月1より、アプリマーケット上の『アプリ』という形で開発者が独自に機能を追加し、スマレジユーザーに売ることが出来るサービスが開始しました。
スマレジ本体のデータのほぼ全てがAPIで公開されているため、店舗の売上や勤怠のリアルタイムのデータを取得できるなど、非常に面白いサービスなのですが、アプリマーケットが賑わわないと、そもそもアプリが使われません(MacのApp Storeがいい例ですね)。アプリ開発にはSaaSサービスとの連携アプリともあって、OpenID Connectなど最低限の実装が少し高いハードルになっています。
そのため、これらの最初に躓く部分を出来る限り取り払い、簡単にアプリを作れるテンプレートとして「スマレジアプリ・スターターパック」を作りました。このパックを使うと、アカウント取得などの事前準備が終わっていれば、約5分でアプリを作成し、スマレジのプラットフォームとつなぐことができます。
OpenID Connectでのログイン機能もスターターパックで提供されるので、アプリの機能に集中することができます。スターターパックという名前の通り、実装したい機能を簡単に追加できるようにしているため、このパックを元に本番アプリの作成・公開も可能です。
本記事では、スターターパックの概要と使用方法を書いています。スターターパックの詳細なしくみやアーキテクチャについては後日別の記事で書きますが、仕組みを理解していなくても問題なくアプリを動かせるようになっています。
特徴
こちらのスターターパックを使うだけで、スマレジのOpenIDでログイン機能を持ち、契約期間内の契約者にはHello Worldを表示するアプリをGoogle Cloud上でデプロイすることができます。アプリの部分を最低限にしていますので、まずHello Worldアプリを実装できたら、簡単にアプリで実装したい機能を追加していくことができます。
以下のような特徴を持っています。
- ユーザー数が100人程度で、月あたりのログイン数が1000アクセス程度の想定で、月額約3円のクラウドコストで収まる設計
- ユーザー数が10万人となっても落ちないスケールアウト設計
- IaCに沿ったパッケージのため、インスタンスの設定やデプロイもすべてコード化されています。ローカルで起動して簡単にテストができ、デプロイもスクリプトを走らせるだけです
- 障害時・エラー時にすぐにアラートが来るようにデフォルトで設定済みです(解除も可能)
構成
全体がサーバーレス構成となっております。Google CloudのFaaSであるCloud Functionを使う構成です。サーバー等のミドルウェアはGoogle Cloudで管理されるため、開発者はそのミドルウェア上で動くコードだけを開発・デプロイすればよい形です。
データベースにはFirestoreというNoSQLを使っておりますが、アプリからの使い勝手もよく、データの確認もGUIで簡単にできます。
- Python3.8ベース
- メインコンポーネント:Cloud Function+Firestore
- サブコンポーネント:Cloud Storage(実行バイナリの保存先)、Error Reporting(アラート用)
必要要件
- MacOSでの開発を想定(スクリプト構成のため)
- Google Cloud環境
- Docker環境
パッケージのダウンロード
GitHubでホストしていますので、こちらから
git cloneしていただくか、ZIPでダウンロードして下さい。
スマレジ・スターターパックのGitHubレポはこちら使い方
事前準備
必要な事前準備は以下の通りです。すでにインストール済みであれば、各項目はスキップしていただいて構いません。
1. スマレジの開発アカウントの取得
2. Google Cloudのアカウント取得、CLIツールのインストール
3. Dockerのインストールスマレジとの連携の関係で、ローカルサーバーだけではアプリを動かせません。パブリックにアクセス可能なサーバーが必要な関係上、Google Cloudでのアカウントを必須にしています。今後、AWSやAzure等で提供できるように機能追加予定です。(もしくは有志の方、ぜひPRお待ちしています!)
1. スマレジ開発アカウントの取得
アカウント申請
スマレジから公式のチュートリアルがあるので、こちらの通りにセットアップして下さい。
https://help.smaregi.jp/hc/ja/articles/360051440053-%E9%96%8B%E7%99%BA%E8%80%85%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8Bスマレジアプリの準備
アプリのキーが必要なため、最初にアプリを登録する必要があります。以下のステップの通り勧めていけば大丈夫です。
2. Google Cloudの準備
Google Cloudは約3万円ほどの無料枠があるので、スターターパックを走らせても課金されることはありません。また、1ヶ月スタータパックを走らせても、100ユーザー程度では月10円もかからず運用できますので、ご安心下さい。必要無くなれば、プロジェクトをまるごと消すことで、全てのリソースを削除できるため、追加で課金されることもありません。
アカウントの作成
こちらの公式ページからスタートして下さい。Googleアカウントが必須となります。
初期セットアップ
Google Cloudのアカウントを作成したら、まずは新しいプロジェクトを作って下さい。今後はこのプロジェクト配下に全てのリソースが配置されます。また、削除も用意になるので、他のプロジェクトがあっても、別で作られることをおすすめします。
次に、FirestoreというデータベースをGUIで作成します。残念ながら、現在(2021-03)ではCLIが提供されていないため、GUI上でセットアップをする必要があります。
CLIツール(Google Cloud SDK)のインストール
こちらの公式ガイドにしたがってGoogle Cloud SDKをインストールして下さい。
3. Dockerの準備
こちらの公式ガイドにしたがってDocker Desktop for Macをインストールして下さい。インストール後、以下を実行してみて動けば問題ありません。
docker run --rm helloworldこれですべての事前準備が完了です!
スターターキットの初期セットアップ
ソースのダウンロードと初期セットアップ
gitからソースコードをcloneして、初期セットアップ用のシェルスクリプトを実行しましょう。このときに作成したGoogle CloudのプロジェクトIDが聞かれるので、入力して下さい。また、Google Cloudへログインするようリクエストされるので、立ち上がったブラウザからログインして下さい。
git clone https://github.com/senbishi21/smaregi-app-starter.git (もしくはzipダウンロードでも可能) smaregi-app-starter/_init/init.shGoogle CloudのFirestoreのページで以下のように表示されたら成功です。
設定情報の入力
_init/credentials/secrets.txtに、スマレジアプリの設定でメモした内容を入力して下さい。ダブルクオート等は不要です。QA_MAIN_URL以外を埋めて下さい。例:
QA_APP_CLIENT_ID=xxxx QA_APP_CLIENT_SECRET=xxxxx PROD_APP_CLIENT_ID=xxxxx PROD_APP_CLIENT_SECRET=xxxxx LOCAL_CONTRACT_ID=xxxx QA_MAIN_URL=変更して下さい PROJECT_ID=xxxアプリの実行とデプロイ -メインページ
cf-main/のフォルダで./run.shを実行すると、ローカルでスタンドアローンで起動するウェブサーバーが動きます。自動でブラウザも開くので、こちらで以下のような画面がでたら成功です。
問題なければ、./deploy.shを実行して下さい。こちらでGoogle CloudのCloud FunctionというFaaSサービスにコードをデプロイします。デプロイには約2分ほどかかります。終了したら、Google CloudでCloud Functionのページを見てみて下さい。以下のように、緑のアイコンとなっていれば成功です。
qa-mainをクリックすると、トリガーURLという項目があるので、それを_init/credentials/secrets.txtのQA_MAIN_URLにコピーして下さい。アプリの実行とデプロイ -OIDCリダイレクトとアプリ利用通知
その後、cf-redirect-OIDC, cf-contract-webhookで./deploy.shを実行して下さい。同じように約2分ほどかかりますので、終了したら、Cloud Functionのページで緑のアイコンとなっていることを確認して下さい。
cf-contract-webhookはアプリの使用を始める時・終了する際に、スマレジ側から呼ばれるWebhook型のサーバー(コンテナ)です。スマレジのアプリ画面で、以下のように設定して下さい。設定のあと、「テスト通知を送信」というボタンを押すと・・・
以下のように契約者情報がFirestoreデータベースに入ったことを確認出来ると思います。これで、アプリの契約が開始・終了した時にデータベースに保存されるようになりました。
完了!
これですべて完了です!cf-mainのURLにアクセスしてみて下さい。以下のようにスマレジのOpenIDのページにリダイレクトされ、ログイン(認証)してアプリを認可すると、以下のように自分のアプリが表示され、契約者IDも反映されるはずです。QA環境では10分でクッキーの有効期限が切れるようになっているので、手早くリダイレクトの動作をテストできます。
あとは、実装したい機能やウェブページをcf-mainにて実装すればOKです!PythonのFlaskをベースにしているので、かなり簡単に機能やロジックの実装ができると思います。
補足
OSSについて
当コードはGitHub上にホストしていますので、PR大歓迎です。ただし、以下のルールを守って頂けると幸いです。
- セキュリティ情報(CloudのTokenやCredential情報等)はDockerfileに入れ込まず、_init/credentialsのフォルダでのみ保持する。こちらのフォルダは.gitignoreで無視されるため、空のテンプレートファイルを_init/credentials-templateに入れ込んで下さい。
- ディレクトリ内でrun.shでローカルに走らせる、deploy.shでクラウド環境にデプロイする、という構成をお願いします。ローカルで走らせることがない場合、run.shをなくすか、echoでその旨を伝えるだけのスクリプトにして下さい。
料金について
料金のシミュレーションはGoogle Cloud price estimateで。
- 100人のユーザーが1000アクセス/月で、5分ごとにスマレジのデータを同期する場合の料金シミュレーションでは月のコストが2.44円です:料金詳細参考ページ
- 10万人のユーザーが全員毎日5アクセスする大規模システムで、5分ごとにスマレジのデータを同期する場合の料金シミュレーションでは月のコストが19万円/月となります:料金詳細参考ページ
スマレジアプリマーケットについて
スマレジアプリマーケットに登録された開発者には、スマレジの担当者からアプリの作り方等について、かなり手厚いサポートが受けられますので、ぜひ活用してみて下さい!私自身もかなりお世話になっています。
また、テクニカルサポートはスマレジ Developers Communityで受け付けているそうで、レスポンスが早い上、機能改善のケースでも実装が早いです。
どちらも、Appl○のiOSアプリや○ndroidアプリストアの対応より相当に早く、サポートも手厚いですので、どんどん使っていくのが早道です。
その他参考資料
- 【スマレジアプリを作ってみた#3】認証機能の実装:こちらの方がOpenIDでのログインの仕組みなど紹介してくださっています。
- 【スマレジアプリを作ってみた#5】Sandboxでの動作確認(テスト):同じ作者の方で、本番環境でのテスト手法を共有してくださってます。
注釈
- 投稿日:2021-03-22T18:18:24+09:00
DockerのVolume領域について
Docker上での記憶領域について
ちょっと気になったのでDockerDesktop for WindowsとLinuxでのDockerのvolumeについてメモ。
確認用コマンド// Docker上のボリューム一覧 docker volume ls //指定ボリュームの詳細情報 docker volume inspect <VOLUME NAME>DockerDesktop for Windows
dockerを利用するために利用しているWindows Subsystem for Linux内にコンテナやイメージが保持されている。
windowsのボリューム上に仮想Linuxディスクイメージが保存されている。
windows用の仮想linuxディスクイメージC:\ProgramData\DockerDesktop\vm-data\Dockerdesktop.vhdxWSL上でのマウントポイントを調べてみると、
仮想Linux上のマウントポイント"Mountpoint": "/var/lib/docker/volumes/<VOLUME NAME>/_data"docker-compose.ymlで指定したvolumesのpathにmongoDBのデータが保存されているっぽい。
DockerEngin(linux)
linux上にdockerを構築した場合はホストOSのボリュームに直接コンテナのデータなどが保存される模様。
dockerのボリューム位置を確認すると以下の場所に格納されていた。Linux上のマウントポイント"Mountpoint": "/var/lib/docker/volumes/<VOLUME NAME>/_data"Mountpointで指定されているpathにアクセスしてみると、実際にコンテナ内のデータを確認することができる。
ボリュームの挙動について
volumeが削除されない限りは
docker-compose.ymlのvolumeの設定を以前のvolumeと同じpathを指定すればmongoDBのデータは引き継がれて使える模様。
(コンテナやイメージを削除してもvolumeは削除されずホストOS内に残っている)
- 投稿日:2021-03-22T17:36:31+09:00
Dockerコンテナのレイヤ構造とは?
はじめに
Dockerfileを書く際のベストプラクティスにもあるように、Dockerfileを作成する際の一般的なガイドラインとして「レイヤの数を最小にすること」というのがあります。普段Dockerfileを書く際にこういったことは意識していますが、そもそもDockerにおけるレイヤとはどのようなものなのか理解していませんでした。
そこで、本記事では「Dockerにおけるレイヤとは何なのか」, 「我々はどういった恩恵を受けているのか」を実際にDockerを操作しながら理解していくことを目的とします。
コンテナイメージのレイヤ構造
Dockerfileを書く際にはまず、
FROM命令でベースとなるイメージを指定します。それに続いて、アプリのインストールやホストからコンテナ内のファイルシステムへのファイルの追加などの変更を加えていきます。このようにコンテナは「変更差分(レイヤ)の集まり」としてみなされます。
作成されたファイルイメージから実行されるコンテナは初め、実行環境中のファイルシステムに何も格納されていない状態です。これに変更差分を加えていき、結果として得られるファイル群をルートファイルシステムとしてコンテナは実行されます。
続いて、コンテナイメージの中身を覗き、レイヤ構造について見ていきます。
例として、Hello World!を返すコンテナを作成します。①helloディレクトリと"Hello World!"を返すシェルスクリプトの作成
$ mkdir hello $ cd hello $ cat <<EOF > ./hello.sh #!/bin/bash echo "Hello World!" exec sleep infinity EOF $ chmod +x hello.sh
echo "Hello World!"でHello World!を出力しますが、これだけだとコンテナが直ぐに終了してしまうため、exec sleep infinityによりこれを防いでいます。②Dockerfileの作成
$ cat <<EOF > ./Dockerfile FROM ubuntu:20.04 COPY ./hello.sh /hello.sh ENTRYPOINT [ "/hello.sh" ] EOF
- FROM命令でベースイメージとしてubuntuの20.04を指定
- COPY命令で実行したいホスト側の
hello.shをコンテナ内にコピー- ENTRYPOINT [ "/hello.sh" ]でコンテナが起動したら、
hello.shを実行するように指示③コンテナイメージのビルド
$ cd hello $ docker build -t hello:v1 ./ $ docker image ls
- helloディレクトリに移動
- コンテナイメージのビルド
- コンテナイメージ(hello:v1)ができていることを確認
④作成したコンテナイメージをtar形式で出力する
docker saveコマンドを使ってコンテナイメージを出力します。$ mkdir dump_hello $ cd dump_hello $ docker save hello:v1 | tar -xC ./ $ tree ./ ./ ├── 07d67c3173ab032b5395d7e292f9c78e669af58c220b94e432784fba43c11adf │ ├── VERSION │ ├── json │ └── layer.tar ├── 5367b0805440d84bce8b0c815a92c29f2c74b0de13f5b82ec524837f496d96dd │ ├── VERSION │ ├── json │ └── layer.tar ├── 6621c71ed3a4a388a2b282106392b5e0d50e1475a53ab64387b1fe5907e05ce4 │ ├── VERSION │ ├── json │ └── layer.tar ├── 8d0b9a80b84810110bed2c2ab8d1aa61e84cb4a28e552a1373e80ed210ebdf24.json ├── 9677226adbb823011a9b00fccba48935af627e2f1c3c8ffd4c033319f8fc07ef │ ├── VERSION │ ├── json │ └── layer.tar ├── manifest.json └── repositories 4 directories, 15 files
- dump_helloディレクトリを作成
- コンテナイメージhello:v1をtar形式で出力
- treeコマンドでコンテナイメージに含まれるファイル群を表示
イメージに含まれるファイル群はおおよそ次のように分類されます。
- layer.tar:コンテナが用いるルートファイルシステムのデータ
- 8d0b9a8...bdf24.json:実行コマンドや環境変数など、実行環境を再現するため情報
- manifest.json, repositories:イメージの構成などに関する情報
- VERSION, json:その他(過去の仕様との互換性のために保持されるファイル群)
このようにコンテナイメージを出力した中身を確認すると
layer.tarというtarファイルがいくつか存在していることが確認できます。これがコンテナイメージを構成するレイヤ群であり、一つ一つがコンテナのルートファイルシステムへの変更差分となっています。
次のコマンドでlayer.tarの中身を確認することができます。$ tar --list -f ./9677226adbb823011a9b00fccba48935af627e2f1c3c8ffd4c033319f8fc07ef/layer.tar | head -n 10 bin boot/ dev/ etc/ etc/.pwd.lock etc/adduser.conf etc/alternatives/ etc/alternatives/README etc/alternatives/awk etc/alternatives/nawkこのようにbinやetcなどのディレクトリなどコンテナのルートファイルシステムを構成するディレクトリがあることが確認できます。
よって、コンテナイメージはコンテナのルートファイルシステムを構成するための変更差分であるレイヤの集合であるということが確認できました。コンテナのビルドとレイヤ構造
先の例ではコンテナのビルド時にDockerfileを使用しました。コンテナのレイヤ構造はこのDockerfileとも深く関係しています。
Dockerfileとは先のようにコンテナイメージの作成手順を記述するファイルであり、命令 引数のようにDockerfileがサポートする命令を行ごとに記述していきます。Dockerはこれを先頭から実行していくことでコンテナイメージを作成します。先の
Hello World!を出力するコンテナイメージに変更を加え、アスキーアートでHello World!と出力するようにします。
アスキーアートを出力するためにはfigletコマンドを使用します。このコマンドでは標準ではubuntuに組み込まれていないため、後からインストールする必要があります。これを踏まえて先のDockerfileを元に新たなDockerfileを作成します。FROM ubuntu:20.04 RUN apt-get update && apt-get install -y figlet #追加 COPY ./hello.sh /hello.sh ENTRYPOINT [ "/hello.sh" ]この
Dockerfileを見ると、FROM命令によりベースイメージとなるubuntu:20.04を指定し、後に続く命令によりベースイメージに変更差分を加えていっていることがわかります。各命令の実行による変更差分はそれぞれレイヤとして結果のイメージに格納されていきます。①コンテナイメージのビルド
次に作成した
Dockerfileを元にしてコンテナイメージのビルドを行います。
ビルドを行う前にhello.shを次のように変更してください。hello.sh#!/bin/bash figlet "Hello World!" #変更 exec sleep infinity$ chmod +x hello.shイメージのビルドを行います。
$ docker build -t hello:v2 ./ Sending build context to Docker daemon 3.072kB Step 1/4 : FROM ubuntu:20.04 ---> 4dd97cefde62 Step 2/4 : RUN apt-get update && apt-get install -y figlet ---> Using cache ---> 1801f21b7c5d Step 3/4 : COPY ./hello.sh /hello.sh ---> db5c2b9ffbad Step 4/4 : ENTRYPOINT [ "/hello.sh" ] ---> Running in a796121286fe Removing intermediate container a796121286fe ---> eff04550fd9d Successfully built eff04550fd9d Successfully tagged hello:v2このようにビルドが完了しました。
②イメージのキャッシュ
Dockerは、Dockerfileの各命令を実行するたびに各変更差分をキャッシュしながらビルドを進めていきます。次回以降ビルドを行う際に、同じ変更差分が期待される場合キャッシュを利用してその実行を省略します。
①で作成したhello.shに変更を加え、出力する文字を変更してみます。hello.sh#!/bin/bash figlet "Hello Docker!" #変更 exec sleep infinity$ chmod +x hello.shイメージのタグをv3にして再度ビルドを行います。
$ docker build -t hello:v3 ./ Step 1/4 : FROM ubuntu:20.04 ---> 4dd97cefde62 Step 2/4 : RUN apt-get update && apt-get install -y figlet ---> Using cache ---> 1801f21b7c5d Step 3/4 : COPY ./hello.sh /hello.sh ---> da3936217988 Step 4/4 : ENTRYPOINT [ "/hello.sh" ] ---> Running in 3f89d674ba12 Removing intermediate container 3f89d674ba12 ---> bc37b1bc7c06 Successfully built bc37b1bc7c06 Successfully tagged hello:v3ビルドのログを見るとStep 2/4 で
Using cacheと出力されていることが確認でき、この時RUN命令は省略されていることがわかります。作成したhello:v2とhello:v3イメージを元にコンテナを起動すると次の出力を得ます。
$ docker run --rm --name hello2 -t hello:v2 _ _ _ _ __ __ _ _ _ | | | | ___| | | ___ \ \ / /__ _ __| | __| | | | |_| |/ _ \ | |/ _ \ \ \ /\ / / _ \| '__| |/ _` | | | _ | __/ | | (_) | \ V V / (_) | | | | (_| |_| |_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_(_)$ docker run --rm --name hello3 -t hello:v3 _ _ _ _ ____ _ _ | | | | ___| | | ___ | _ \ ___ ___| | _____ _ __| | | |_| |/ _ \ | |/ _ \ | | | |/ _ \ / __| |/ / _ \ '__| | | _ | __/ | | (_) | | |_| | (_) | (__| < __/ | |_| |_| |_|\___|_|_|\___/ |____/ \___/ \___|_|\_\___|_| (_)このようにどちらも期待した結果を出力できていることが確認できました。
sleep infinityをさせているため、別ウインドウを開き、コンテナを終了させます。$ docker kill hello2 $ docker kill hello3このようにコンテナのビルドはイメージのレイヤ構造と深い関係があり、ビルダはこのレイヤ構造を利用したキャッシュの仕組みも備えていることがわかります。
Dockerfileを作成する際にレイヤを意識することは重要で、レイヤをまとめることでイメージを軽量にしたりベースイメージとしてより軽量なものを用いたりとDockerfileを書く際のベストプラクティスとして様々な方法が議論されています。コンテナ実行時のレイヤ構造
同じコンテナイメージから作成されるコンテナが並列に稼働する場合があります。
例として、先のコンテナイメージhello:v2を元に2つのコンテナをバックグラウンドで立ち上げてみます。$ docker run -d --rm --name hello2 hello:v2 $ docker run -d --rm --name hello3 hello:v2hello2コンテナに変更を加えて、それぞれのコンテナを参照してみます。
$ docker exec hello2 /bin/bash -c 'echo "New File!" > /newfile.txt' $ docker exec hello2 cat /newfile.txt New File! $ docker exec hello3 cat /newfile.txt cat: /newfile.txt: No such file or directoryこのように、共通のイメージから作成されたコンテナ同士でも、片方のコンテナがルートファイルシステムに施した変更は他のコンテナからは見えないようになっています。
リソースを無駄にせずにこれを実現するためには、「コンテナ同士がデータの重複を起こさずにコンテナ同士の環境が影響し合わないようにする」ということが要求されており、これを可能にするのがレイヤ構造です。
ホスト上でDockerはコンテナイメージをそのレイヤ構造を保ったまま保持しており、イメージからコンテナを実行する際にはそのレイヤ群を重ね合わせた結果をコンテナのルートファイルシステムとして使用していました。
また、Dockerでは、共通のコンテナイメージからコンテナを実行する際、共通のレイヤ群をコピーせず共有しています。この時、イメージを構成していたレイヤ群は読み取り専用としてコンテナ間で共有されるため、そのレイヤの内容が他のコンテナにより意図せず書き換えられることがありません。
一方で、先の例のようにルートファイルシステムに書き込みを行った場合はコンテナの実行時にはレイヤ群を重ね合わせた一段上にそのコンテナ専用の読み書き可能レイヤを新たに作成することで書き込みを行います。この読み書き可能レイヤにはコンテナの実行に伴うルートファイルシステムへの変更差分のみが格納されています。つまり、あるファイルが作成された場合、その作成されたファイルのみが読み書き可能レイヤに格納されます。また、読み取り専用である下位のレイヤに含まれるファイルに変更を加える場合、変更対象のファイルのみ読み書き可能レイヤにコピーされ変更が加えられます。
このようにコンテナのレイヤ構造により、それぞれのコンテナは他のコンテナによって意図せず書き換えられることなく、ファイルの重複が起こらないようになっているため、効率良くリソースを使うことができています。まとめ
本記事では、Dockerコンテナのレイヤ構造に注目し、レイヤとはどういったものであるのか、どのような恩恵を得ることができるのかについて調べました。コンテナイメージ、コンテナのビルド、コンテナの実行とレイヤ構造の関係をそれぞれ調べ、以下の結論を得ました。
- コンテナイメージはコンテナのルートファイルシステムを構成するための変更差分であるレイヤの集合である
- コンテナのビルドはイメージのレイヤ構造と深い関係があり、ビルダはこのレイヤ構造を利用したキャッシュの仕組みも備えている
- コンテナのレイヤ構造により、それぞれのコンテナは他のコンテナによって意図せず書き換えられることなく、ファイルの重複が起こらないようになっている
また、レイヤ構造のイメージからルートファイルシステムを作成する際に用いられる方法など、より詳細な点については筆者が参考文献として利用したイラストでわかるDockerとKubernetessを参照されると良いかと思います。
参考文献
- 投稿日:2021-03-22T17:08:41+09:00
docker-compose Rails + Postgresql環境構築
作業ディレクトリと必要なファイルを作成
まず開発していくディレクトリとアプリケーションを構築するために必要なファイルを作成する
必要なファイル
Dockerfile
Gemfile
Gemfile.lock
entrypoint.sh
docker-compose.yml
$ mkdir myapp $ cd myapp $ touch {Dockerfile,Gemfile,Gemfile.lock,entrypoint.sh,docker-compose.yml} $ ls Dockerfile Gemfile.lock entrypoint.sh Gemfile docker-compose.ymlファイルの中身を記述してく
Rails6ではwebpackerが搭載されyarnのインストールが必要
DockerfileFROM ruby:2.6.6 RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN bundle install COPY . /myapp # Add a script to be executed every time the container starts. COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 # Start the main process.Gemfilesource 'https://rubygems.org' gem 'rails', '6.0.3'entrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /myapp/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"docker-compose.ymlversion: '3' services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=password web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" depends_on: - dbプロジェクトの構築
作成したファイルを利用してdocker-compose runを実行しアプリケーションを生成
$ docker-compose run web rails new . --force --no-deps --database=postgresqlそして
$ docker-compose build . . . Successfully built 0b14a3eedc73 Successfully tagged myapp_web:latestimageを構築
- 投稿日:2021-03-22T10:50:28+09:00
DjangoとReactで作成したアプリにDockerを組み込む
Dockerとは
一言で言うとコンテナ型のアプリケーション実行環境のこと。
DockerがあればどのPCからでも、簡単にそのアプリを実装できる環境を構築することができる。今回やること
前回私が開発したアプリにDockerを組み込んで環境構築を容易にしていく。
そのアプリの開発記事↓
DjangoとReactでPDCAアプリを作る その1作業の流れ
1.requirements.txtの作成
2.Django用Dockerfileの作成
3.nodejs用Dockerfileの作成
4.docker-composeの作成
requirements.txtの作成
完成したアプリのディレクトリ下で以下のコマンドを実行するとそのアプリでインストールしたライブラリをrequirements.txtにまとめることができる
pip freeze > requirements.txtなお、アプリ開発を行うにあたって
Virtualenvを使って、専用の開発環境を準備した方が良い。
そうしてから取り組めば、そのアプリ開発でインストールしたライブラリだけをrequreiments.txtに落とし込むことができる。virtualenvについての記事↓
venv: Python 仮想環境管理Django用Dockerfileの作成
# pythonの基本的な環境をubuntuで構築している↓↓ FROM ubuntu:18.04 RUN apt-get -y update \ && apt-get -y upgrade \ && apt-get install -y locales curl python3-distutils \ && curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \ && python3 get-pip.py \ && pip install -U pip \ && mkdir /code \ && rm -rf /var/lib/apt/lists/* \ && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 ENV LANG en_US.utf8 # ↑↑ # 作成したrequirementsをコンテナ側へcopy COPY ./requirements.txt /requirements.txt # コンテナ側でアプリに必要なライブラリをインストール RUN pip install -r /requirements.txt # アプリを置くためのディレクトリを作成 RUN mkdir /workapp # 起動時に最初に開かれるディレクトリを設定 WORKDIR /workapp # 作成したアプリをコンテナ側へcopy COPY ./workapp /workappnodejs用Dockerfileの作成
FROM node:10.13-alpinedocker-composeの作成
docker-composeとは、
dockerでこのコンテナを立てる際に使うであろうdockerコマンドを1つのファイルにまとめてくれるツール
version: '3' services: app: build: context: . tty: true stdin_open: true ports: - "8000:8000" # コンテナ側から実際の環境側にあるアプリを参照する volumes: - ./workapp:/workapp command: > sh -c "python3 manage.py migrate && python3 manage.py runserver 0.0.0.0:8000" depends_on: - react react: build: context: . dockerfile: "./Dockerfile-nodejs" volumes: - ./work_react:/work_react command: > sh -c "cd work_react && npm start" ports: - "3000:3000"dockerを起動してアプリディレクトリ下で、以下のコマンドを実行する
docker-compose upこれで無事、djangoとReactで開発したアプリにDockerを組み込むことができた?
今後の展望
今回は、DBをsqliteのままにしてDockerを組み込んだので、次回は、postgresSQLを用いて組み込めるようにしたい。
また、nginx等のwebサーバーも用いて、開発現場さながらのDockerコンテナを作成したいと考えているここまで読んでくださりありがとうございました?♂️?♂️
また、Twitterでも日々の積み上げや、プログラミング学習についてのツイートをしておりますので、よかったらフォローと応援の程よろしくお願いします!?♂️
Twitterアカウント↓
健将@WEBエンジニア×明大生
- 投稿日:2021-03-22T09:36:01+09:00
elmをdockerでmakeする
codesimple/elm
いつからあったのか分からないが、手持ちの環境にelmをインストールしなくてもdockerで開発できる環境が整うので試してみた。
コマンド
使い方は簡単で自分の開発環境で以下コマンドを実行するだけ。
docker run --rm -it -v $(pwd):/code -w /code -e "HOME=/tmp" codesimple/elm:0.19 make src/Main.elm --output=main.jsmake意外にもinitとかinstall、reactorもelmコマンドがそのまま入っているのでお気軽。
There are a bunch of other commands as well though. Here is a full list: elm repl --help elm init --help elm reactor --help elm make --help elm install --help elm bump --help elm diff --help elm publish --helpGithub Actionsでgithub.ioにデプロイ
せっかくなのでこのdocker imageを使って、以前elmで作ったぷよぷよゲームをGithub Actionsで自動デプロイしてみる。
- masterでmake
- 生成物とその他もろもろの必要なファイルを/tmp/codeに退避
- github.io用のブランチにチェックアウト
- 退避したファイルで色々上書きしてcommit&push
name: Deploy Github.io on: push: branches: [master] jobs: deploy: runs-on: ubuntu-latest container: codesimple/elm:0.19 steps: - uses: actions/checkout@v2 - name: Install dependencies run: elm make --output=main.js src/Main.elm - name: saving data run: cp -r ./ /tmp/code - name: install git run: apk add git - name: git setting run: | git config --global user.email "email" git config --global user.name "name" - uses: actions/checkout@v2 with: ref: gh-pages - name: copy files run: | cp /tmp/code/main.js ./main.js cp /tmp/code/src/main.css ./src/main.css cp -r /tmp/code/api ./api cp /tmp/code/index.html ./index.html - name: Commit files run: | git add . git commit -m "update" -a git push origin gh-pages感想
elmの開発環境はもともと構築が簡単だけど、さらに楽に開発できてとても助かった。
個人的にはdockerでreactor立てておくだけで簡単にローカルお試し環境ができるのが最高。github actionsはめちゃめちゃ便利。
elm-gamesのdemoとかはgithub.ioを使って公開している人が多かったので一度やってみたかった。
- 投稿日:2021-03-22T07:52:44+09:00
k8sな開発環境であると便利なTelepresenceをCentos7にInstallする
Telepresence
Telepresenceはk8sを利用した開発時に開発マシンにinstallしていると便利なもので、指定したk8s上のpodをproxy podに置き換えて、k8s上のpodへの通信をlocalのコンテナに、localのコンテナからの通信をproxy podからk8s上に返すことができるツールです。
Telepresence: https://www.telepresence.io/
TelepresenceをCentOS7にinstall
install手順は公式のここに書いてあるのですが、CentOS7用の手順がありません。検索するとこれがでてきますが微妙に動かないのでinstall手順を以下に整理しました。
- 作業ディレクトリ作成
install作業中にgit cloneコマンドを実行してtelepresenceリポジトリを落としてきたりするので作業用ディレクトリを作って作業します。
mkdir telepresence cd telepresence
- telepresence_centos7.sh作成 コマンドを順番に実行しても良いのですがinstallスクリプトをtelepresence_centos7.shとして作成してinstall作業を進めます。以下の内容でtelepresence_centos7.shを作成してください。
#!/bin/bash set -ex yum update -y # install python3.6 yum -y install yum-utils yum -y groupinstall development yum install -y https://repo.ius.io/ius-release-el7.rpm yum -y install python36u #echo "`python3.6 -v` installed." # python 3.6 installed # install system dependencies yum install -y git torsocks sshfs conntrack git clone https://github.com/datawire/telepresence.git && cd telepresence # force the install to use python3.6 sed -i "s/python3/python3.6/" install.sh env PREFIX=/usr/local ./install.sh echo "Telepresence `telepresence --version` installed!"
- install実行
bash telepresence_centos7.sh最後に
Telepresence 0.109-16-g601cad6-dirty installed!などと出力されれば成功です。telepresenceコマンドが使えるようになっているはずです。
- 投稿日:2021-03-22T00:41:21+09:00
Docker + React (Typescript) + Rails6 環境構築
Summary
バックエンド Rails API & フロントエンド React & Docker の環境を実現したので手順をメモしておく
- Rails 初期設定ファイル作成
- Rails & React 用のDocker関連ファイル作成
- docker-compose.yml 作成
- docker コマンド実行
- database.yml の変更
- docker-compose で起動
ファイル構成
1. Rails 初期設定ファイル作成
Gemfilesource 'https://rubygems.org' gem 'rails', '=>6'Gemfile.lock# 空2. Rails & React 用のDocker関連ファイル作成
Rails
DockerfileFROM ruby:2.7.2 # Rails6 からは以下のインストールが必要 # https://yarnpkg.com/lang/en/docs/install/#debian-stable RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -qq && apt-get install -y nodejs postgresql-client vim && \ apt-get install -y yarn && \ apt-get install -y imagemagick && \ apt-get install -y libvips-tools && \ apt-get install -y locales RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - && \ apt-get install nodejs RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN bundle install COPY . /myapp COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0"]entrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /myapp/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"React
DockerfileFROM node:14.16.0-alpine3.10 WORKDIR /usr/src/app3. docker-compose.yml の作成
docker-compose.ymlversion: "3.9" services: db: image: postgres volumes: - postgres-data:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=password api: build: context: ./api/ dockerfile: Dockerfile command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - ./api:/myapp - ./api/vendor/bundle:/myapp/vendor/bundle environment: TZ: Asia/Tokyo RAILS_ENV: development ports: - 3000:3000 depends_on: - db front: build: context: ./front/ dockerfile: Dockerfile volumes: - ./front:/usr/src/app command: sh -c "cd frontend && yarn start" ports: - "8000:3000" volumes: postgres-data: driver: local4. docker コマンド実行
$ docker-compose run api rails new . --force --no-deps --database=postgresql --api $ docker-compose build # yarn でインストール、Typescript 対応 $ docker-compose run --rm front sh -c "yarn create react-app frontend --template typescript"5. database.yml の変更
config/database.ymldefault: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>6. docker-compose で起動
$ docker-compose up -d $ docker-compose run api rails db:create参考




















