20210322のdockerに関する記事は10件です。

dockerコンテナの中でviが使えない場合

環境

docker desktop for windows
AWS EC2+docker

現象

docker execでコンテナの中に入ったらviが使えなかった。。

手順

下記の手順でviが使えるようになりました。

  1. docker exec -it {apache00} bash
  2. apt-get update
  3. apt-get install vim

appendix

Centos系

yum install vim

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 docker

docker-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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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

スマレジアプリの準備

アプリのキーが必要なため、最初にアプリを登録する必要があります。以下のステップの通り勧めていけば大丈夫です。
Screen Shot 2021-03-21 at 18.50.22.png
Screen Shot 2021-03-21 at 18.50.22.png
Screen Shot 2021-03-21 at 18.50.22.png
Screen Shot 2021-03-21 at 18.50.22.png

2. Google Cloudの準備

Google Cloudは約3万円ほどの無料枠があるので、スターターパックを走らせても課金されることはありません。また、1ヶ月スタータパックを走らせても、100ユーザー程度では月10円もかからず運用できますので、ご安心下さい。必要無くなれば、プロジェクトをまるごと消すことで、全てのリソースを削除できるため、追加で課金されることもありません。

アカウントの作成

こちらの公式ページからスタートして下さい。Googleアカウントが必須となります。

初期セットアップ

Google Cloudのアカウントを作成したら、まずは新しいプロジェクトを作って下さい。今後はこのプロジェクト配下に全てのリソースが配置されます。また、削除も用意になるので、他のプロジェクトがあっても、別で作られることをおすすめします。

Screen Shot 2021-03-21 at 16.37.53.png

次に、FirestoreというデータベースをGUIで作成します。残念ながら、現在(2021-03)ではCLIが提供されていないため、GUI上でセットアップをする必要があります。
Screen Shot 2021-03-21 at 18.50.22.png

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.sh

Screen Shot 2021-03-22 at 13.09.07.png

Google CloudのFirestoreのページで以下のように表示されたら成功です。
Screen Shot 2021-03-21 at 19.43.08.png

設定情報の入力

_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を実行すると、ローカルでスタンドアローンで起動するウェブサーバーが動きます。自動でブラウザも開くので、こちらで以下のような画面がでたら成功です。

Screen Shot 2021-03-22 at 9.36.15 copy.png

問題なければ、./deploy.shを実行して下さい。こちらでGoogle CloudのCloud FunctionというFaaSサービスにコードをデプロイします。デプロイには約2分ほどかかります。終了したら、Google CloudでCloud Functionのページを見てみて下さい。以下のように、緑のアイコンとなっていれば成功です。
Screen Shot 2021-03-22 at 13.54.25.png
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型のサーバー(コンテナ)です。スマレジのアプリ画面で、以下のように設定して下さい。設定のあと、「テスト通知を送信」というボタンを押すと・・・
Screen Shot 2021-03-21 at 21.13.20.png

以下のように契約者情報がFirestoreデータベースに入ったことを確認出来ると思います。これで、アプリの契約が開始・終了した時にデータベースに保存されるようになりました。
Screen Shot 2021-03-21 at 21.16.17.png

完了!

これですべて完了です!cf-mainのURLにアクセスしてみて下さい。以下のようにスマレジのOpenIDのページにリダイレクトされ、ログイン(認証)してアプリを認可すると、以下のように自分のアプリが表示され、契約者IDも反映されるはずです。QA環境では10分でクッキーの有効期限が切れるようになっているので、手早くリダイレクトの動作をテストできます。

  • Screen Shot 2021-03-22 at 7.59.12.png Screen Shot 2021-03-22 at 9.36.15.png

あとは、実装したい機能やウェブページを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アプリストアの対応より相当に早く、サポートも手厚いですので、どんどん使っていくのが早道です。

その他参考資料

注釈

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.vhdx

WSL上でのマウントポイントを調べてみると、

仮想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内に残っている)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerコンテナのレイヤ構造とは?

はじめに

Dockerfileを書く際のベストプラクティスにもあるように、Dockerfileを作成する際の一般的なガイドラインとして「レイヤの数を最小にすること」というのがあります。普段Dockerfileを書く際にこういったことは意識していますが、そもそもDockerにおけるレイヤとはどのようなものなのか理解していませんでした。

そこで、本記事では「Dockerにおけるレイヤとは何なのか」, 「我々はどういった恩恵を受けているのか」を実際にDockerを操作しながら理解していくことを目的とします。

コンテナイメージのレイヤ構造

Dockerfileを書く際にはまず、FROM命令でベースとなるイメージを指定します。それに続いて、アプリのインストールやホストからコンテナ内のファイルシステムへのファイルの追加などの変更を加えていきます。このようにコンテナは「変更差分(レイヤ)の集まり」としてみなされます。
スクリーンショット 2021-03-20 15 54 26
作成されたファイルイメージから実行されるコンテナは初め、実行環境中のファイルシステムに何も格納されていない状態です。これに変更差分を加えていき、結果として得られるファイル群をルートファイルシステムとしてコンテナは実行されます。
続いて、コンテナイメージの中身を覗き、レイヤ構造について見ていきます。
例として、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を指定し、後に続く命令によりベースイメージに変更差分を加えていっていることがわかります。各命令の実行による変更差分はそれぞれレイヤとして結果のイメージに格納されていきます。

スクリーンショット 2021-03-22 11 57 21

①コンテナイメージのビルド

次に作成した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:v2

hello2コンテナに変更を加えて、それぞれのコンテナを参照してみます。

$ 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では、共通のコンテナイメージからコンテナを実行する際、共通のレイヤ群をコピーせず共有しています。この時、イメージを構成していたレイヤ群は読み取り専用としてコンテナ間で共有されるため、そのレイヤの内容が他のコンテナにより意図せず書き換えられることがありません。
一方で、先の例のようにルートファイルシステムに書き込みを行った場合はコンテナの実行時にはレイヤ群を重ね合わせた一段上にそのコンテナ専用の読み書き可能レイヤを新たに作成することで書き込みを行います。

スクリーンショット 2021-03-22 17 00 39

この読み書き可能レイヤにはコンテナの実行に伴うルートファイルシステムへの変更差分のみが格納されています。つまり、あるファイルが作成された場合、その作成されたファイルのみが読み書き可能レイヤに格納されます。また、読み取り専用である下位のレイヤに含まれるファイルに変更を加える場合、変更対象のファイルのみ読み書き可能レイヤにコピーされ変更が加えられます。
このようにコンテナのレイヤ構造により、それぞれのコンテナは他のコンテナによって意図せず書き換えられることなく、ファイルの重複が起こらないようになっているため、効率良くリソースを使うことができています。

まとめ

本記事では、Dockerコンテナのレイヤ構造に注目し、レイヤとはどういったものであるのか、どのような恩恵を得ることができるのかについて調べました。コンテナイメージ、コンテナのビルド、コンテナの実行とレイヤ構造の関係をそれぞれ調べ、以下の結論を得ました。

  • コンテナイメージはコンテナのルートファイルシステムを構成するための変更差分であるレイヤの集合である
  • コンテナのビルドはイメージのレイヤ構造と深い関係があり、ビルダはこのレイヤ構造を利用したキャッシュの仕組みも備えている
  • コンテナのレイヤ構造により、それぞれのコンテナは他のコンテナによって意図せず書き換えられることなく、ファイルの重複が起こらないようになっている

また、レイヤ構造のイメージからルートファイルシステムを作成する際に用いられる方法など、より詳細な点については筆者が参考文献として利用したイラストでわかるDockerとKubernetessを参照されると良いかと思います。

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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のインストールが必要

Dockerfile
FROM 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.
Gemfile
source '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.yml
version: '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:latest

imageを構築

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 /workapp

nodejs用Dockerfileの作成

FROM node:10.13-alpine

docker-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エンジニア×明大生

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.js

make意外にも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 --help

Github Actionsでgithub.ioにデプロイ

せっかくなのでこのdocker imageを使って、以前elmで作ったぷよぷよゲームをGithub Actionsで自動デプロイしてみる。

コードはここ

  1. masterでmake
  2. 生成物とその他もろもろの必要なファイルを/tmp/codeに退避
  3. github.io用のブランチにチェックアウト
  4. 退避したファイルで色々上書きして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

ちゃんと動き出した。
image.png

demo

795a92ae-119e-9ee0-1699-569e525ae843.png

感想

elmの開発環境はもともと構築が簡単だけど、さらに楽に開発できてとても助かった。
個人的にはdockerでreactor立てておくだけで簡単にローカルお試し環境ができるのが最高。

github actionsはめちゃめちゃ便利。
elm-gamesのdemoとかはgithub.ioを使って公開している人が多かったので一度やってみたかった。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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コマンドが使えるようになっているはずです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker + React (Typescript) + Rails6 環境構築

Summary

バックエンド Rails API & フロントエンド React & Docker の環境を実現したので手順をメモしておく

  1. Rails 初期設定ファイル作成
  2. Rails & React 用のDocker関連ファイル作成
  3. docker-compose.yml 作成
  4. docker コマンド実行
  5. database.yml の変更
  6. docker-compose で起動

ファイル構成

image.png

1. Rails 初期設定ファイル作成

Gemfile
source 'https://rubygems.org'
gem 'rails', '=>6'
Gemfile.lock
# 空

2. Rails & React 用のDocker関連ファイル作成

Rails

Dockerfile
FROM 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

Dockerfile
FROM node:14.16.0-alpine3.10
WORKDIR /usr/src/app

3. docker-compose.yml の作成

docker-compose.yml
version: "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: local

4. 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.yml
default: &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

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む