- 投稿日:2020-07-22T22:03:28+09:00
Dockerでubuntuイメージを取得してきてコンテナ起動する
https://hub.docker.com/_/ubuntu を起動する時のコマンドメモ。
ふとlinuxコマンドを動かしたくなった時にさっと使えるようにメモです。イメージの取得
docker pull ubuntuコンテナをバックグラウンドで起動
docker run --name <container_name> -it -d <image_name> /bin/bash# 例 docker run --name ubuntu -it -d ubuntu /bin/bashシェルに入る
docker exec -it <container_name> /bin/bash# 例 docker exec -it ubuntu /bin/bashおまけ
コンテナ名をつけ忘れたり間違えてしまったら
docker rename
でコンテナ名を変更できる。docker rename <current_name> <new_name>manを使いたい
シェル内からman読もうと思ったらミニマムな構成とのことでそのままだと使えなかった(コンテナってこういうものだよね…)
root@10b70c6ce5aa:/# man mount This system has been minimized by removing packages and content that are not required on a system that users do not log into. To restore this content, including manpages, you can run the 'unminimize' command. You will still need to ensure the 'man-db' package is installed.
unminimize
叩いてみたroot@10b70c6ce5aa:/# unminimize This system has been minimized by removing packages and content that are not required on a system that users do not log into. <snip>2回くらい[y/n]聞かれるので
Y
押すリトライ
root@10b70c6ce5aa:/# man mount bash: /usr/bin/man: No such file or directoryそもそもいなかった(コンテナってこういうものd)
更新&インストール(いつもの)
root@10b70c6ce5aa:/# apt update root@10b70c6ce5aa:/# apt install -y manパッケージ一覧確認
root@10b70c6ce5aa:/# dpkg -l | grep man <snip> ii man-db 2.9.1-1 amd64 tools for reading manual pages <snip>
man-db
が増えたroot@10b70c6ce5aa:/# man mount今度はman見れるようになりました!
- 投稿日:2020-07-22T17:40:12+09:00
flaskアプリをdockerfileを使用しherokuへデプロイ
今回は完成しているフラスクアプリをdockerfileから動かしherokuでデプロイするまでを記述します。
ネットを探してもあまりいい記事が見つからずあまり普段はほとんど見ることのない公式のドキュメントを見て実行することにしました。
heroku公式ドキュメントDockerfile
FROM ubuntu:latest RUN apt-get update RUN apt-get install python3 python3-pip -y COPY . /home WORKDIR /home RUN pip3 install -r requirements.txt RUN pip3 install email_validator RUN ls /home ENV FLASK_APP app.py RUN echo $FLASK_APP RUN flask db init RUN flask db migrate RUN flask db upgrade RUN ls /home CMD flask run -h 0.0.0.0 -p $PORTherokuにdockerとしてデプロイする時に重要なのは下の行です。
CMD flask run -h 0.0.0.0 -p $PORT
$PORTについてはheroku側でうまくやってくれるらしいです。herokuへデプロイ作業
$ mkdir project $ cd project $ git clone <自分で作成したdockerfileが置いてあるリポジトリ> $ heroku login $ heroku create $ heroku container:push web $ heroku container:release web $ heroku open<>の中以外はそのまま入力しました。
修正してまたデプロイするとき
$ heroku container:push web $ heroku container:release web
- 投稿日:2020-07-22T16:20:51+09:00
Depends_on、Volumes、Init Docker-composeオプション - Docker Composeのための実践演習その3
このチュートリアルでは、Alibaba Cloud上でコンテナを扱う際にDocker Composeを使用して実践的な経験を積むことに焦点を当てています。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
depends_on
depends_onはサービス間の依存関係を宣言します。
depends_on docker-compose upでは、依存関係のある順にサービスを起動します。
依存関係にあるサービスは、メインサービスが起動する前に最初に起動します。
見ての通り、依存関係はランダムな順番で開始されます。また、docker-compose はメインサービスを起動する前に依存関係の実行を待つことはありません。
これを実際に見てみましょう。
docker-compose.yml に以下を追加します。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 depends_on: - service-2 - service-3 - service-4 container_name: main-container service-2: image: alpine:3.8 container_name: service-2 command: sleep 600 service-3: image: alpine:3.8 container_name: service-3 command: sleep 600 service-4: image: alpine:3.8 container_name: service-4 command: sleep 600依存関係はきちんと番号順に宣言されていることに注意してください。
このdocker-composeファイルを以下のようにして起動してみましょう。
docker-compose up -d -t 0期待される出力 .
Creating service-3 ... done Creating service-4 ... done Creating service-2 ... done Recreating compose-tuts_alpine_1 ... done依存関係がランダムな順番で始まっていることに注意してください。メインサービスは最後に開始されますが、上記の出力には明確には表示されていません。
docker-compose ファイルに小さな編集を加えて (スリープ時間の編集など)、docker-compose をやり直すと、これらのサービスが毎回異なるシーケンスで作成されていることがわかります。試してみてください。
イベントのシーケンスをより明確に見るために、すべてのサービスをシャットダウンしてdocker-compose upをやり直してみましょう。
docker-compose down -t 0期待される出力 .
Stopping main-container ... done Stopping service-4 ... done Stopping service-3 ... done Stopping service-2 ... done Removing main-container ... done Removing service-4 ... done Removing service-3 ... done Removing service-2 … doneネットワークcompose-tuts_defaultの削除
メインコンテナが最初に停止し、次に依存関係が停止することに注意してください。ここで実行します。
docker-compose up -d -t 0期待される出力 .
Creating network "compose-tuts_default" with the default driver Creating service-3 ... done Creating service-2 ... done Creating service-4 ... done Creating main-container ... done最後に作成されたメインコンテナが明確に表示されます。
メインコンテナが起動する前に依存サービスをREADYにしておく必要がある場合は、 https://docs.docker.com/compose/startup-order/ を勉強する必要があります。
volumes
volumesは、名前付きvolumesのマウントに使用されます。
これを面白くするために、先ほどの例の4つのサービスを再利用します。
4 つのサービスはすべて demo-data-volume という名前付きvolumesを使用します。これはまだ存在しません。
docker-compose.ymlに以下を追加します。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 depends_on: - service-2 - service-3 - service-4 container_name: main-container service-2: image: alpine:3.8 container_name: service-2 command: sleep 600 volumes: - demo-data-volume:/root/dir1/dir2 service-3: image: alpine:3.8 container_name: service-3 command: sleep 600 volumes: - demo-data-volume:/root/dira/dirb service-4: image: alpine:3.8 container_name: service-4 command: sleep 600 volumes: - demo-data-volume:/root/1/2/3/4 volumes: demo-data-volume:一番下の右側:これがトップレベルのボリュームキーです(Dockerのドキュメントでは名前が付けられています)。
トップレベルのキーはdocker-composeファイルの左端から始まります。
トップレベルのキーはdemo-data-volumeを定義しています。
実行時には
docker-compose up -d -t 0demo-data-volumeが作成されます(存在しない場合)。
期待される出力は以下の通りです。
Creating network "compose-tuts_default" with the default driver Creating volume "compose-tuts_demo-data-volume" with default driver Creating service-2 ... done Creating service-4 ... done Creating service-3 ... done Creating main-container ... done2行目の注意点 compose-tuts_demo-data-volume "をデフォルトドライバで作成します。
実行します。
docker volume ls期待される出力 .
DRIVER VOLUME NAME local compose-tuts_demo-data-volumeこれが名前付きvolumesです。この名前は、カレントディレクトリと docker-compose ファイルで指定したボリューム名を連結したものです。
docker-compose ファイルでは、この名前付きボリュームを 3 つのサービスの異なるマウントポイントで使用するように定義しました。
service-2: volumes: - demo-data-volume:/root/dir1/dir2 service-3: volumes: - demo-data-volume:/root/dira/dirb service-4: volumes: - demo-data-volume:/root/1/2/3/4ここでは、これら3つのサービスがすべて同じ名前のvolumesにアクセスできることを確認します。
service-2 を入力して、名前付きvolumesで作業してみましょう。
docker exec -it service-2 /bin/shls はパスが存在することを示し、echo は myoutfile を作成します。そして終了します。
/ # ls /root/dir1 dir2 / # echo from service 2 > /root/dir1/dir2/myoutfile / # exitservice-3に入って、名前のついたvolumesを調べてみましょう。
docker exec -it service-3 /bin/shls はファイルが存在することを確認します。
/ # ls /root/dira/dirb myoutfile / # cat /root/dira/dirb/myoutfile from service 2 / # exitservice-3では、volumesは/root/dira/dirbにマウントされていることに注意してください。
service-3: volumes: - demo-data-volume:/root/dira/dirbサービス4では、volumesは/root/1/2/3/4にマウントされていることに注意してください。
service-4: volumes: - demo-data-volume:/root/1/2/3/4ファイルがそこで利用可能であることを確認するために、service-4を入力します。
docker exec -it service-4 /bin/sh期待される出力 .
/ # cat /root/1/2/3/4/myoutfile from service 2 / # exit私たちの名前のついたボリュームは、この3つのコンテナの中で読み書きすることができます。これらのコンテナを停止しても存在し続けます。
他のコンテナ、サービス、スワームはこの名前付きボリュームの使用を許可されています。この名前付きボリュームは、これら3つのサービスとは特にリンクしていません。
この数分間で、あなたはおそらくDockerボリュームの機能の5%未満を探索しました。
https://docs.docker.com/engine/extend/legacy_plugins/#volume-plugins には25以上のvolumesプラグインがリストアップされています。
公式ドキュメントは https://docs.docker.com/storage/volumes/ と https://docs.docker.com/storage/ で読むことができます。
少なくともこれで、名前付きvolumesを実際に使ってみて、その仕組みをある程度理解したことになるでしょう。
幸いなことに、名前付きvolumesは最も理解しやすく、最も柔軟性があり、最も頻繁に使用されています。
restart
restartはdocker-compose upを使ってサービスを起動する際に適用されます。
わかりやすい4つのオプションがあります。
1、restart:"no" ... デフォルト値
2、restart: always
3、restart: on-failure
4、restart:unless-stopped
それらを試してみましょう。**restartのためのデモ:"no" ... the default value
以下を docker-compose.yml に追加します。nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 1サービスを起動します。
docker-compose up -d -t 0その状態を確認します。
docker ps -asleep 1 は、コンテナをわずか 1 秒後に終了させます。
docker ps -a を何度も実行しても、終了したコンテナは 1 つしか表示されません。予想通り: restart = no はコンテナを再起動しません。
restart のデモ: unless-stop
を使用して、以下を docker-compose.yml に追加します。nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 1 restart: unless-stopped前のコンテナをプルーンして、クリーンなdocker ps -aで作業を行います。
docker container prune -f;docker ps -a新しいコンテナを起動します。
docker-compose up -d -t 0その状態を確認します。
docker ps -asleep 1 は、コンテナをわずか 1 秒後に終了させます。
このコマンドを繰り返し実行すると、コンテナが継続的に再起動していることがわかります。
docker container stop your-container-id を実行してもコンテナは停止しません。
docker-compose down は数秒以内にコンテナを削除します。
docker-compose up を使ってコンテナを起動した場合は、docker-compose down を使ってコンテナを削除します。
restart: unless-stopped は期待通りに動作します。
restartのデモ: always
を使用して、以下を docker-compose.yml に追加します。nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 1 restart: always新しいコンテナを起動します。
docker-compose up -d -t 0その状態を確認します。
docker ps -asleep 1 は、コンテナをわずか 1 秒後に終了させます。
このコマンドを繰り返し実行すると、コンテナは継続的に再起動します。
docker container stop your-container-id does not stop it. docker-compose down removes the container within seconds.docker-compose up を使ってコンテナを起動した場合は、docker-compose down を使ってコンテナをダウンさせます。
restart:alwaysは終了コードがゼロ ( 成功 ) で終了したコンテナを常に再起動します。
Commandを置き換えると
command: sleep 1; exit 1restart: always は 0 以外の ( 失敗した ) 終了コードで終了するコンテナを再起動することをテストできます。
restart: on-failure のデモ
新しいソフトウェアを学ぶには、ドキュメントを読んで、それを使うことが必要です。経験値ゼロを意味します。
実験は経験を意味します。
ですから、上記で経験したことに基づいて、再起動のためのテストを設計して実行してください:on-failure
失敗した場合のコンテナの再起動をテストしなければなりません。
また、正常に終了した場合に再起動するかどうかもテストしなければなりません ( exit return code 0 )。
上記のテキストに基づいて、これは最大で5分かかるはずです。
init: true の未設定
https://docs.docker.com/compose/compose-file/#init より
コンテナ内で init を実行して、シグナルを転送したり、プロセスを再生したりします。デフォルトの init を使用するには、init を true に設定します。
コンテナ内のプロセスをクリーンにシャットダウンさせたい場合は、このオプションをtrueに設定することが重要です。
docker container stopを実行した場合、コンテナ内のプロセスはコンテナに転送された正しいシグナルを受信しなければなりません。そうすれば、アプリケーションのシャットダウンサブルーチンは正しくシグナルを受けてクリーンにシャットダウンされます。
コンテナ内で複数のプログラムやスレッドを実行している場合、それらは何らかの全体的な管理者プロセスによって正しく管理されたSTOPシグナルを受信しなければなりません。INIT はそのプロセスです。
以下の説明を実際の例で見てみましょう。
Init は最初に SIGTERM (シグナル 15) を送信し、プロセスがそのシグナルをキャッチしてクリーンシャットダウンルーチンを実行できるようにします。SIGTERM は - シャットダウンしなければならないが、最初にクリーンシャットダウンルーチンを実行することを意味します。
stop_grace_period = 10 seconds default.stop_grace_period は、SIGKILL (シグナル9) を送信する前に、コンテナがクリーンに終了するのを10秒間待ちます。SIGKILL は直ちにプロセスを終了させます - ファイルが適切に閉じられていない - シャットダウンルーチンは実行されていません。SIGKILL は、ある瞬間にはプロセスが動いていることを意味し、次の瞬間には頭が吹っ飛びます。
init: true を指定した場合のみ、この重要なシグナルがコンテナ内に適切に伝わります。
まとめ : データの破損を防ぎたい場合は init: true を指定してください。
重要: このオプションはバージョン3.7のファイルフォーマットで追加されました。docker-compose.yml の最初の行は version. “3.7”
まず、init設定をしないとSTOPの扱いが悪くなることを確認します。
次に、init: trueを指定して違いを観察することで正しく処理します。
docker-compose.ymlに以下のように追加します。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8新しいコンテナを起動します。
docker-compose up -d -t 0コンテナの状態を確認し、コンテナIDを取得します。
docker ps -a docker exec -it your-container-id /bin/shそれを入力してpsを実行します。
/ # ps PID USER TIME COMMAND 1 root 0:00 sleep 600 11 root 0:00 /bin/sh 16 root 0:00 ps / # exitPIDプロセス1がinitされていないことに注意してください。
新しいシェルコンソールを開き、docker eventsを実行します。
元のシェルに戻って
docker container stop your-container-idと表示されると、停止するのに10秒かかることがわかります。
重要: docker イベントのコンソール出力を見てください。
期待される出力 .
2018-11-12T09:51:46.112995194+02:00 container kill b676e3bf51f9f1f99edc531ffa04b0ab164834cb218fe9b78abb65b396782d6a (com.docker.compose.config-hash=c19f3ca3bb22826fee98596d3cb40c4f403f8a51cede518945f5ef37bb989589, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=compose-tuts, com.docker.compose.service=alpine, com.docker.compose.version=1.22.0, image=alpine:3.8, name=compose-tuts_alpine_1, signal=15) 2018-11-12T09:51:56.134707392+02:00 container kill b676e3bf51f9f1f99edc531ffa04b0ab164834cb218fe9b78abb65b396782d6a (com.docker.compose.config-hash=c19f3ca3bb22826fee98596d3cb40c4f403f8a51cede518945f5ef37bb989589, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=compose-tuts, com.docker.compose.service=alpine, com.docker.compose.version=1.22.0, image=alpine:3.8, name=compose-tuts_alpine_1, signal=9) 2018-11-12T09:51:56.307015745+02:00 container die b676e3bf51f9f1f99edc531ffa04b0ab164834cb218fe9b78abb65b396782d6a (com.docker.compose.config-hash=c19f3ca3bb22826fee98596d3cb40c4f403f8a51cede518945f5ef37bb989589, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=compose-tuts, com.docker.compose.service=alpine, com.docker.compose.version=1.22.0, exitCode=137, image=alpine:3.8, name=compose-tuts_alpine_1) 2018-11-12T09:51:56.387969293+02:00 network disconnect 9802e2506ea80e7597f0b018450f86fa0c7dcc045a920702cc0e463aacfda84f (container=b676e3bf51f9f1f99edc531ffa04b0ab164834cb218fe9b78abb65b396782d6a, name=compose-tuts_default, type=bridge) 2018-11-12T09:51:56.454351535+02:00 container stop b676e3bf51f9f1f99edc531ffa04b0ab164834cb218fe9b78abb65b396782d6a (com.docker.compose.config-hash=c19f3ca3bb22826fee98596d3cb40c4f403f8a51cede518945f5ef37bb989589, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=compose-tuts, com.docker.compose.service=alpine, com.docker.compose.version=1.22.0, image=alpine:3.8, name=compose-tuts_alpine_1)最初のイベントはコンテナのSIGTERM - その行の最後にsignal15のテキストを右に送信します。
Dockerはコンテナがまだ適切にシャットダウンされていないと判断します。コンテナはsignal15を無視します。
2行目。KILLシグナルイベントは10秒後に発生します - その行の最後にsignal 9のテキストが表示されます。
Dockerはsignal 9 = KILLでコンテナーを強制終了します。
まとめ: initもなく、秩序あるシャットダウンもできず、killを使わなければなりませんでした。
init: true
では、initがどのように停止を適切に処理するかを観察してみましょう。
次のようにして、docker-compose.ymlに以下を追加します。
nano docker-compose.yml version: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 init: trueinit: trueで新しいコンテナを起動します。
docker-compose up -d -t 0状態を確認してコンテナIDを取得します。
docker ps -a docker exec -it your-container-id /bin/shそれを入力してpsを実行します。
/ # ps PID USER TIME COMMAND 1 root 0:00 /dev/init -- sleep 600 6 root 0:00 sleep 600 7 root 0:00 /bin/sh 12 root 0:00 ps / # exitPID 1 は /dev/init を実行していることに注意してください。initはPID 1を実行しています:コンテナ内のすべてのプロセスへのシグナル送信を管理するための唯一の完璧な場所です。
docker eventsコンソールでCTRL-cを押して、イベントのリストが中断されるようにします。
このコンソールで再び docker events を実行します - 今度は INIT で管理されているシャットダウンイベントを観察します。
元のシェルに戻り、docker ps -a でコンテナ ID を取得します。
今実行した場合
docker container stop your-container-idと表示されると、非常に早く停止することがわかります。
重要: docker イベントのコンソール出力を見てください。
期待される出力 .
2018-11-12T09:50:14.892684432+02:00 container kill 7973ccec4849cf8759821d613e1b4870c68d76f396fefcfb1cd1bf1f7a3bd509 (com.docker.compose.config-hash=8d5184879de73d9f624319983822eafca40959cbe9f91929ff4648ace18acc6a, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=compose-tuts, com.docker.compose.service=alpine, com.docker.compose.version=1.22.0, image=alpine:3.8, name=compose-tuts_alpine_1, signal=15) 2018-11-12T09:50:15.019039627+02:00 container die 7973ccec4849cf8759821d613e1b4870c68d76f396fefcfb1cd1bf1f7a3bd509 (com.docker.compose.config-hash=8d5184879de73d9f624319983822eafca40959cbe9f91929ff4648ace18acc6a, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=compose-tuts, com.docker.compose.service=alpine, com.docker.compose.version=1.22.0, exitCode=143, image=alpine:3.8, name=compose-tuts_alpine_1) 2018-11-12T09:50:15.104203647+02:00 network disconnect 9802e2506ea80e7597f0b018450f86fa0c7dcc045a920702cc0e463aacfda84f (container=7973ccec4849cf8759821d613e1b4870c68d76f396fefcfb1cd1bf1f7a3bd509, name=compose-tuts_default, type=bridge) 2018-11-12T09:50:15.149018229+02:00 container stop 7973ccec4849cf8759821d613e1b4870c68d76f396fefcfb1cd1bf1f7a3bd509 (com.docker.compose.config-hash=8d5184879de73d9f624319983822eafca40959cbe9f91929ff4648ace18acc6a, com.docker.compose.container-number=1, com.docker.compose.oneoff=False, com.docker.compose.project=compose-tuts, com.docker.compose.service=alpine, com.docker.compose.version=1.22.0, image=alpine:3.8, name=compose-tuts_alpine_1)最初のイベントはコンテナのSIGTERM - その行の最後にsignal15のテキストを送信します。
Dockerはコンテナが適切にシャットダウンされていると判断します。コンテナはsignal15を適切に処理する。( コンテナの処理はsignal15をキャッチし、クリーンシャットダウンルーチンを呼び出します。)
コンテナのダイイベントは100ミリ秒後に発生します。
NO signal 9 = KILLが送信されました。
まとめ: init、高速な秩序あるシャットダウン、KILLは使用されません。
要するに、init: trueを使用することを強くお勧めします。これは簡単で高速で、破損したデータの手間を省くことができます。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-07-22T14:52:10+09:00
コンテナサービスを使ったDockerコンテナクラスタの作成方法
このチュートリアルでは、Alibaba Cloudのコンテナサービスを使ってDockerコンテナクラスタを作成する方法を紹介します。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
アリババクラウドのコンテナサービスとは?
Alibaba Cloud's Container Serviceは、スケーラブルで高性能なコンテナ管理サービスで、Docker SwarmまたはKubernetesのいずれかを使用してコンテナ化されたアプリケーションのライフサイクルをオーケストレーションして管理することができます。
Alibaba Cloudのコンテナサービスは、継続的インテグレーションを含む複数のアプリケーションリリース方法を提供し、マイクロサービスアーキテクチャもサポートしています。Alibaba Cloudの仮想化、ストレージ、ネットワーク、セキュリティサービスと統合されたコンテナクラスタのUI設定を簡素化することで、Alibaba Cloudのコンテナサービスは、コンテナ化されたアプリケーション環境の実行、管理、監視に最適なクラウド環境となっています。
Docker Swarmとは?
Dockerはオープンソースの仮想化管理ツールで、コンテナ内でアプリケーションやシステムを開発、デプロイ、管理、監視することができます。このプロセスはコンテナ化と呼ばれています。Docker Swarmは、複数のスケーラブルなDockerコンテナ上で動作するシステムや環境のためのクラスタリング、スケジューリング、オーケストレーションツールです。
Dockerコンテナは、コード、ランタイム、ライブラリ、環境変数、設定ファイルなど、アプリケーション全体の実行に必要なすべてを含む実行可能パッケージであるDockerイメージを実行することで起動します。コンテナはDockerイメージのランタイムインスタンスです。
同じインスタンス上で複数のコンテナを同時に実行したり、インスタンスのクラスタスウォームを実行したりすることができ、コンテナはオペレーティングシステムのハイパーバイザーの代わりにDockerによって管理されます。これにより、1つ以上のクラスタノードに問題が発生した場合の冗長性とフェイルオーバーを提供します。
Dockerは軽量で効率的で、複数のアプリケーションで構築された最も複雑なシステムを管理することができます。ローカルでDockerコンテナを構築し、クラウドにデプロイして、必要な場所でスケールアップ、スケールダウンして実行することができます。
Dockerは、単一のECSインスタンス上で簡単にセットアップ、インストール、実行できます。業界レベルのアプリケーションやシステムを実行する大規模なコンテナ化環境には、信頼性と拡張性に優れたオーケストレーションと監視システムが必要です。Alibaba Cloudのコンテナサービスは、システム管理者やDevOpsチームに、大規模なコンテナ化環境を管理するために必要なクラスタ化アーキテクチャを提供します。
クラスタを作成する必要がある理由
Alibaba Cloudのコンテナサービスで実行中のDockerコンテナのスイートをインストールする前に、コンテナ化されたシステムを実装するためのAlibaba Cloud Container Service Docker Swarmクラスタを準備して利用できるようにしておく必要があります。
このチュートリアルでは、そのようなクラスタを構築するための予備的なステップを説明します。次のチュートリアルでは、Alibaba Cloudのコンテナサービスを使ってDocker SwarmクラスタにDockerイメージを実装する方法を紹介します。
前提条件
Alibaba Cloudアカウントが必要です。アカウントをお持ちでない場合は、無料トライアルのページにアクセスして、Alibaba Cloud New User Free Trialで300ドル相当のAlibaba Cloud製品にアクセスして遊んでみましょう。
それでは、始めましょう。
クラスタの作成
まず、商品ページに向かい、コンテナサービスをクリックします。
Container Serviceコンソールページに到着します。
Create Clusterをクリックする前に、Container Service Swarmオプションが選択されていることを確認してください。
クラスタにユニークな名前をつけ、RegionとZoneを選択してください。
クラスタのVPCの詳細とIPの初期CIDRブロック範囲を確認します。
既存のECSインスタンスをクラスタに追加することも、新しいインスタンスを作成することもできます。このチュートリアルでは、クラスタ用に4つの小さなインスタンスを作成してみましょう。
必要に応じてデータストレージを追加してください - しかし、各ECSインスタンスには最低限のストレージが付属しています。
OSはUbuntuかCentosのどちらかを選択できます。
安全にアクセスするためのキーペアを設定したり、必要に応じてインスタンスにアクセスするためのルートパスワードを設定したりすることができます。
オプションのチェックを外してパブリックIPアドレス(EIP)を設定したままにしておき、インスタンスにもクラウド監視プラグインをインストールします。
クラスタにはServer Load Balancerが自動的に作成されるように設定されています。
必要に応じて、クラスタ上で事前に設定した Relation Database Service (RDS) インスタンスを選択することができ、クラスタ作成プロセスでは、Virtual Private Cloud (VPC) 上の関連するプロトコルタイプのセキュリティグループが設定されます。
設定の詳細に問題がなければ、ページの上部にある「作成」をクリックします。
作成をクリックすると、クラスタ構成の詳細をまとめたページが表示され、確認を求められます。
クラスタ構成が必要に応じて適切であることを確認したら、[OK]をクリックします。
リクエストが送信されました。クラスタの作成中にレポートログが表示されます。
必要なサービスがまだ起動していないという警告に気づいた場合は、先に進みましょう。
クラスタが作成されると、画面上に確認画面が表示されます。
クラスタ一覧に戻るをクリックします。
クラスタリストには、利用可能なクラスタと実行中のクラスタが表示されます。
ここで、Overviewをクリックすると、クラスタのグラフィカルな表示が表示されます。
Nodes をクリックすると、クラスタを構成するパブリックおよびプライベートIPアドレス、ステータス、その他の設定情報を含む ECS インスタンスのリストが表示されます。
この例のアプリケーション、サービス、コンテナのセクションには、デフォルトのビルドシステムのアプリケーションとサービス、インスタンスごとに自動的に含まれる7つのコンテナの情報がリストアップされています。
これで、先ほど作成したAlibaba Cloud Container Serviceクラスタ上にDocker Swarmコンテナ化システムをセットアップする準備が整いました。
まとめ
最初に、Alibaba Cloud Container Serviceのアプリケーション環境を動かすためのクラスタを構築するとお伝えしましたが、今回のチュートリアルではDocker Swarmクラスタになります。今後のチュートリアルでは、コンテナサービスのKubernetesオプション用のクラスタも構築する予定です。
続いて、Alibaba Cloudのコンテナサービス製品について簡単に説明し、その高性能、スケーラビリティ、使いやすいコンソールが、コンテナ化されたアプリケーション環境をAlibaba Cloudの膨大な製品やサービスと統合するのに最適な方法であることを説明しました。
チュートリアルの最初の部分では、Docker Swarmクラスタを構築して、実行中のアプリケーションを構成するDockerコンテナを選択してDocker Swarmアプリケーションを構築することを説明しました。
最後に、Alibaba Cloud Container ServiceのDocker Swarmクラスタを構築するプロセスをステップバイステップで説明し、設定オプションを説明しながら進めていきます。
次のチュートリアルでは、Alibaba Cloudのコンテナサービスを使ってDocker Swarmクラスタ上に実行中のアプリケーション環境を構築する方法を紹介します。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-07-22T14:16:56+09:00
Dockerコンテナのクリーンアップの実務経験
このチュートリアルでは、Alibaba Cloud上のDockerコンテナのクリーンアップを実践的に体験できます。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
準備
このチュートリアルに従うには、Dockerが既にインストールされているAlibaba Cloud Elastic Compute Service (ECS)サーバーが必要です。方法がわからない場合は、このチュートリアルを参考にしてください。
コンテナのクリーンアップについて学ぶために、クリーンアップするコンテナがいくつか必要です。
まず、https://hub.docker.com/ からいくつかのイメージが必要です。
このチュートリアルでは、画像の中に何が入っているかは全く問題ではありません。このチュートリアルを完全に理解するためには、Nginx、Redis、Alpineの経験は必要ありません。
Redisはオープンソースのインメモリデータ構造ストアで、データベースやデータキャッシュとして使用されています。ほとんどのプログラミング言語は、メモリ内のデータにほぼ瞬時にアクセスすることで、プログラムを高速化するために使用することができます。
NGINXは無料でオープンソースの高性能HTTPサーバーです。
Alpine Linuxは5MBのLinuxディストリビューションで、dockerユーザーに非常に人気があります。
Alpine Linuxは、dockerアプリケーションのベースイメージとして使用されています。これは、アプリを実行するための小さなLinux環境を提供します。
シェルプロンプトで次のように入力して、これらの4つのイメージをコンピュータにダウンロードしてください。
docker pull hello-world:latest docker pull nginx:mainline-alpine docker pull redis:alpine docker pull alpine:3.8docker pulコマンドはレジストリからDockerイメージをダウンロードします。docker レジストリには Docker イメージのコレクションが含まれています。
デフォルトでは、docker pull コマンドは Docker Hub: https://hub.docker.com/ から docker イメージをプル/ダウンロードします。
Dockerイメージは、実行中のコンテナを作成するために使用されます。Docker イメージには、特定のアプリケーションを実行するために必要なすべてのソフトウェアが含まれています。例えば、ダウンロードしたnginx:mainline-alpineイメージには、コンテナ内でNginxを実行するために必要なすべてのソフトウェアが含まれています。
docker pull nginx:mainline-alpineでは、nginx:mainline-alpineはプル/ダウンロードしたいイメージの名前です。画像名はnginxです。
mainline-alpineはタグです。タグは同じイメージの異なるバージョンを区別するために使われます。例えば、Docker Hubのリポジトリにはnginx:centos、nginx:ubuntu、nginx:debian8、nginx:debian9のイメージがあります。どのイメージをダウンロードするかを正確に指定するためにタグを使用しています。
docker pull alpine:3.8の場合、3.8タグはバージョン番号を表しています。
実行します。
docker ps -a期待される出力。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES新鮮なdockerインストールサーバーでこれを実行している場合は、実行中のコンテナがありません。
混乱させて、いくつかのコンテナを作成して片付けてみましょう。以下のコマンドを入力します。
docker run --name nginx -d nginx:mainline-alpine docker run --name redis -d redis:alpine docker run -d hello-world docker run -d hello-world docker run -d hello-worlddocker runは、以前にダウンロードした静的イメージを実行コンテナに変えてくれます。
コンテナとは、dockerイメージのランタイム版のことです。コンテナには、実行中のプロセスを含む完全な実行環境だけでなく、Dockerイメージのすべてのソフトウェアが含まれています。
このチュートリアルではnginxやredisの機能は必要ありません。必要なのは、多様なコンテナの興味深いリストだけです。そうすれば、コンテナを選択的に停止したり削除したりする方法をよりよく学ぶことができます。
nginx と redis を停止してみましょう。hello-world コンテナはメッセージを表示して終了するだけです。すでに停止しているので、停止させる必要はありません。
docker stop nginxdocker stop redisこのコマンドを入力して、すべてのコンテナを一覧表示します。
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 97f95b11260e hello-world "/hello" 57 seconds ago Exited (0) 44 seconds ago determined_payne 91f69bd08bf8 hello-world "/hello" About a minute ago Exited (0) About a minute ago xenodochial_wiles 6f7b53de6ad7 hello-world "/hello" About a minute ago Exited (0) About a minute ago pedantic_bartik 62919b9e6d84 redis:alpine "docker-entrypoint.s? About a minute ago Exited (0) 3 seconds ago redis 49ca281f8a0c nginx:mainline-alpine "nginx -g 'daemon of? 2 minutes ago Exited (0) 14 seconds ago nginxThe CONTAINER IDs you get when you run these commands on your computer will be different.現在、5つのコンテナが停止しています。
使用できません。
docker container pruneこのコマンドは停止している全てのコンテナをプルーニング/削除します。ここでは、まだ nginx と redis のログを見たいと仮定します。そのため、hello-world コンテナだけを慎重にプルーニングしなければなりません。
hello-world コンテナだけのリストを作成してみましょう。実行します。
docker ps -a | grep "hello-world"grep は、hello-world というテキストを含む出力行のみを選択します。
grep はほとんどの Linux ディストリビューションに搭載されている Linux シェルユーティリティです。40年前に書かれました。
grep is used to search plain-text input for lines that match its search expression. The __ docker ps -a __ lists all containers, the pipe symbol | sends this list to grep. __ grep "hello-world" __ searches for the text __ hello-word __. grep only outputs the list of containers __ containing hello-word. __ Grep stands for: g/re/p (__g__lobally search a __re__gular expression and __p__rint) In __ docker ps -a | grep "hello-world" __ grep searched the list of containers output by docker ps, and prints only the lines containing hello-world. grep searches the input files for lines containing a match to a given pattern list. When it finds a match in a line, it copies the line to standard output (by default), or whatever other sort of output you have requested with options.期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 97f95b11260e hello-world "/hello" About a minute ago Exited (0) About a minute ago determined_payne 91f69bd08bf8 hello-world "/hello" 2 minutes ago Exited (0) About a minute ago xenodochial_wiles 6f7b53de6ad7 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago pedantic_bartik完璧です。プルーニングしたいコンテナのリストが必要です。
代わりに実行することもできます。
docker ps -a | egrep --invert-match "redis|nginx"-invert-matchはマッチングを反転させ、マッチングしていない行のみを選択します。-v は --invert-match のショートカットです。
"redis|nginx "は、redisまたはnginxを含むテキストのみを選択する正規表現です。ここで、パイプ記号の|は、「または」を意味します。
ここで、egrepは、redisとnginxを含むテキストを除いた出力行のみを選択します。
ここではegrepを使用しています: このgrepは拡張正規表現をサポートしています。この場合、"redis|nginx "は拡張正規表現をサポートしています。
docker container __ rm __ = docker container __ remove __ / delete / prunedocker container rmのフォーマットは以下の通りです。
docker container rm [OPTIONS] CONTAINER [CONTAINER...]docker コンテナ rm に渡すコンテナ ID のリストが必要です。
コンテナIDは出力の最初のフィールド番号です。 awk '{print $1}' は、渡された最初のフィールドだけを出力します。
AWKはテキスト処理のために設計されたプログラミング言語です。テキストデータを抽出したりフィルタリングしたりするのに使われます。ほとんどのLinuxディストリビューションにインストールされています。
AWKは1970年に作成されました。AWKの名前は作者のAlfred Aho, Peter Weinberger, Brian Kernighanの名字に由来しています。
awkとgrepはどちらもテキストをフィルタリングします。grepは入力された列を選択的に印刷することができません。これは awk だけが持っている機能です。そのため、grepとawkを使う必要があります。
awk '{print $1}' は、渡された最初のフィールドだけを表示します。 awk のデフォルトでは、フィールドは空白文字で区切られていると仮定しています。awk '{print $1}' __を使用すると、ここではコンテナのIDを表示しますが、これはdocker ps -aの出力の最初のフィールド/列です。
実行します。
docker ps -a | grep "hello-world" | awk '{print $1}'期待される出力
97f95b11260e 91f69bd08bf8 6f7b53de6ad73つのhello-worldコンテナをすべて削除してみましょう。以下のコマンドのいずれかを選択して実行します。
docker ps -a | grep "hello-world" | awk '{print $1}' | __ xargs docker container rm __或いは
docker ps -a | egrep -v "redis|nginx" | awk '{print $1}' | __ xargs docker container rm __xargs docker container rmはコンテナIDを一つずつ受信して削除します。
期待される出力
97f95b11260e 91f69bd08bf8 6f7b53de6ad7完璧です。 docker container rmには削除したコンテナIDが表示されています。
実行します。
docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 62919b9e6d84 redis:alpine "docker-entrypoint.s? 4 minutes ago Exited (0) 2 minutes ago redis 49ca281f8a0c nginx:mainline-alpine "nginx -g 'daemon of? 4 minutes ago Exited (0) 2 minutes ago nginxredis と nginx はまだ存在しています。
redis と nginx のログを調べて、それらのコンテナも削除できるようにしておきましょう。
dockerのログはコンテナのログを表示します。docker logs redis1:C 03 Oct 06:40:25.554 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1:C 03 Oct 06:40:25.559 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1, just started 1:C 03 Oct 06:40:25.559 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 1:M 03 Oct 06:40:25.613 * Running mode=standalone, port=6379. 1:M 03 Oct 06:40:25.614 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 1:M 03 Oct 06:40:25.614 # Server initialized 1:M 03 Oct 06:40:25.614 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. 1:M 03 Oct 06:40:25.615 * Ready to accept connections 1:signal-handler (1538548914) Received SIGTERM scheduling shutdown... 1:M 03 Oct 06:41:54.159 # User requested shutdown... 1:M 03 Oct 06:41:54.195 * Saving the final RDB snapshot before exiting. 1:M 03 Oct 06:41:54.233 * DB saved on disk 1:M 03 Oct 06:41:54.233 # Redis is now ready to exit, bye bye...実行します。
docker logs nginx何も表示されません。nginxコンテナも何も使っていませんでした。
ログの調査完了しました。これで全てのコンテナを削除することができます。
実行します。
docker container prune -fDeleted Containers: 62919b9e6d844d6720301dd8be7d0dfb58defb593fe8e9fa1ea0984b7aa92baa 49ca281f8a0cdc3adaddd222a654c4e61b17861f3a20dd9b584d0073466c722d Total reclaimed space: 0B2つのコンテナIDが表示されています。これらのコンテナも削除されました。
実行します。
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES予想通り、コンテナの稼働も停止もありません。
概要
まず、コンテナを削除するには、必要なテキストだけを grepping してから awk でコンテナ ID だけを選択する方法を学びました。
次にコンテナIDをxargs docker container rmに渡すと、渡されたコンテナが削除されます。
docker ps -a | grep "hello-world" | awk '{print $1}' | xargs docker container rm代用します:
docker ps -a | egrep -v "redis|nginx" | awk '{print $1}' | xargs docker container rmDocker Container Pruneを使用してコンテナーを削除
docker run -d hello-worldさらに2回実行して、3つのコンテナをクリーンアップするようにします。
docker run hello-world ; docker run hello-world実行します。
docker container ls実行中のコンテナしか表示されないので、何も表示されません。
実行します。
docker container ls -a-aは全てのコンテナを表示します。
期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 60cc61444c0b hello-world "/hello" 45 seconds ago Exited (0) 37 seconds ago pensive_albattani e820b8032706 hello-world "/hello" About a minute ago Exited (0) 51 seconds ago silly_lovelace 7e959fd100d0 hello-world "/hello" About a minute ago Exited (0) About a minute ago fervent_kilby
docker container prune
コマンドは停止しているコンテナをすべて削除します。コマンド
docker container prune --force
は停止しているコンテナをすべて削除しますが、確認のためのプロンプトは表示されません。実行します。
docker container prune -f期待される出力
Deleted Containers: 60cc61444c0b90c7f2b0ada1546c3913a93676bbb0ba0dfb1c9329268222df6d e820b803270681be048b511d676af56e28778e92ef783a536a4272f7d9648bd6 7e959fd100d0a72311f25987a0d0b6d1960283f2b164e56c538baddad83e8446総埋立面積:0B
3つのコンテナを削除しました。prune オプションの -f は --force のショートカットです。
ラベルを使ったコンテナのプルーニング
ラベルは、関連するコンテナをグループ化するためにdockerで使用されます。そして、ラベルの値に基づいてそれを選択することで、コンテナを選択的に処理することができます。
コマンド docker container prune は、ラベルをフィルターとして使用したコンテナの削除をサポートしています。
現在サポートされているフィルタは以下の通りです。
until () - 指定されたタイムスタンプより前に作成されたコンテナのみを削除します。
label - 指定したラベルが付いている(label!=...の場合は付いていない)コンテナのみを削除します。
今回はラベルを使って3つのコンテナを作成してみましょう。
以下の3つのコマンドを実行します。
docker run -d --label hello-1 hello-world docker run -d --label hello-2 hello-world docker run -d --label hello-3 hello-worlddocker ps -a コマンドはラベルを表示しません。ラベルを表示するには --format オプションを使う必要があります。
完全な --format のリファレンスは
https://docs.docker.com/engine/reference/commandline/ps/#formatting
実行します。
docker ps -a --format 'table {{.Image}}\t{{.Labels}}\t{{.Command}}\t{{.Status}}'期待される出力
IMAGE LABELS COMMAND STATUS hello-world hello-3= "/hello" Exited (0) 1 minutes ago hello-world hello-2= "/hello" Exited (0) 1 minutes ago hello-world hello-1= "/hello" Exited (0) 1 minutes ago実行してhello-1コンテナだけを選択的にpruneしてみましょう。
docker container prune --force --filter "label=hello-1”期待される出力
Deleted Containers: 1aa4c41c7a5b164edb4bb08cec4ec8c9769fb3e7dc311c825321fc7f87989ea9 Total reclaimed space: 0Bコマンドを再実行します。
docker ps -a --format 'table {{.Image}}\t{{.Labels}}\t{{.Command}}\t{{.Status}}'IMAGE LABELS COMMAND STATUS hello-world hello-3= "/hello" Exited (0) 4 minutes ago hello-world hello-2= "/hello" Exited (0) 4 minutes agoこれで残りのコンテナは2つになりました。
この2つのコンテナを実行してプルーニングしてみましょう。
docker container prune -f実行します。
docker ps -a期待される出力
IMAGE LABELS COMMAND STATUSすべてのコンテナをプルーニングしました。ラベルは、特定のラベルで1つのコンテナを選択的にプルーニングするのに便利です。
複数のコンテナが同じラベルを共有している場合には、複数のコンテナをプルーニング
するのと同じように便利です。Docker ps フィルタリングのリファレンス
https://docs.docker.com/engine/reference/commandline/ps/#filtering より
name:::コンテナ名
label::: キーまたはキーと値のペアを表す任意の文字列。または = のように表現される。
ancestor:::: 指定された画像を共有するコンテナをancestorとしてフィルタリングします。
volume:::指定されたボリュームまたはバインドマウントをマウントした実行中のコンテナをフィルタリングします。
network:::指定されたネットワークに接続されているコンテナをフィルタリングします。
publish or expose::: を実行しているコンテナをフィルタリングします。指定されたポートを公開または公開するコンテナをフィルタリングします。port[/protocol]で表現されます。
これら3つのコンテナは同じ祖先イメージを共有しています。hello-word:latest__は、このコマンド一つで簡単にプルーニングすることができました。
docker container prune --force --filter __ "ancestor=hello-word:latest" __これら3つのコンテナが同じネットワークを使用している場合、例えば mytestnetwork__ のように、このコマンド一つで簡単にプルーニングできました。
docker container prune --force --filter __ "network=mytestnetwork" __終了ステータスを使用したコンテナのプルーニング
終了ステータスは、終了したコンテナ内のプロセスの成功ステータスを表します。
終了ステータスが0の場合、通常は成功を意味します(オペレーティングシステムやプログラミング言語では、終了ステータス0=成功)。
終了ステータスの特定の数値は、特定のプログラミング言語やプログラムで定義された値を持っています。例えば、404はNginxとApacheのウェブサーバでウェブページが見つからないことを意味します。
以下の123と9の終了ステータスは、単に乱数であり、異なる終了ステータスを持つコンテナをクリーンアップする方法を示すために使用されています。
以下のコマンドを実行して、4つの異なる終了ステータスコードを持つ5つのコンテナを作成します。
docker run -d alpine:3.8 /bin/sh -c 'exit 123' docker run -d alpine:3.8 /bin/sh -c 'exit 9' docker run -d alpine:3.8 docker run --name nginx -d nginx:mainline-alpine docker run --name redis -d redis:alpine以下を実行して、コンテナの一覧とステータスの終了コードを表示します。
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9d4163879e17 redis:alpine "docker-entrypoint.s? 13 seconds ago Up 3 seconds 6379/tcp redis 2754c6805252 nginx:mainline-alpine "nginx -g 'daemon of? 26 seconds ago Up 15 seconds 80/tcp nginx ef02229f40da alpine:3.8 "/bin/sh" 42 seconds ago Exited (0) 30 seconds ago epic_nobel 857cf388b70c alpine:3.8 "/bin/sh -c 'exit 9'" 59 seconds ago Exited (9) 46 seconds ago peaceful_torvalds 8b084d95a2fb alpine:3.8 "/bin/sh -c 'exit 12? About a minute ago Exited (123) About a minute ago pedantic_mirzakhaninginxとredisが実行されていますが、まだ終了コードはありません。
では実行してみましょう。
docker ps -a --filter status=exited期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ef02229f40da alpine:3.8 "/bin/sh" About a minute ago Exited (0) About a minute ago epic_nobel 857cf388b70c alpine:3.8 "/bin/sh -c 'exit 9'" About a minute ago Exited (9) About a minute ago peaceful_torvalds 8b084d95a2fb alpine:3.8 "/bin/sh -c 'exit 12? 2 minutes ago Exited (123) About a minute ago pedantic_mirzakhani--filter status=exitedを指定してから、3つの終了したコンテナだけが表示されました。
docker ps -a --filter 'exited=0’期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ef02229f40da alpine:3.8 "/bin/sh" About a minute ago Exited (0) About a minute ago epic_nobel終了したコンテナは1つだけ表示されます。
実行します。
docker ps -a --filter 'exited=123’期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8b084d95a2fb alpine:3.8 "/bin/sh -c 'exit 12? 2 minutes ago Exited (123) 2 minutes ago pedantic_mirzakhani終了したコンテナが1つだけ表示されています:exited status = 123
終了ステータス=0のコンテナを削除してみましょう。
docker ps -a --filter 'exited=0' | awk '{print $1}' | xargs docker container rm実行します。
ef02229f40da Error: No such container: CONTAINER実行します。
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9d4163879e17 redis:alpine "docker-entrypoint.s? 4 minutes ago Up 3 minutes 6379/tcp redis 2754c6805252 nginx:mainline-alpine "nginx -g 'daemon of? 4 minutes ago Up 4 minutes 80/tcp nginx 857cf388b70c alpine:3.8 "/bin/sh -c 'exit 9'" 4 minutes ago Exited (9) 4 minutes ago peaceful_torvalds 8b084d95a2fb alpine:3.8 "/bin/sh -c 'exit 12? 5 minutes ago Exited (123) 4 minutes ago pedantic_mirzakhaniexited=0 コンテナの削除に成功しました。
なぜエラーが出るのか:
Error: そのようなコンテナはありません。: CONTAINER実行してみてください。
docker ps -a --filter 'exited=9' | awk '{print $1}’期待される出力
CONTAINER 857cf388b70cそのCONTAINERヘッダーが問題です。xargs docker container rm にはコンテナ ID のリストだけを渡すべきです。
問題を修正するには、grep: grep -v CONTAINERを使ってCONTAINERヘッダの行を削除してください。
-v は --invert-match のショートカットです。
実行します。
docker ps -a --filter 'exited=9' | awk '{print $1}' | grep -v CONTAINER期待される出力
857cf388b70cSuccess: CONTAINER ヘッダー行が表示されていません。
この2行は同じ結果になっています。
docker ps -a --filter 'exited=9' | awk '{print $1}' | grep -v CONTAINERここでは、docker psは、9つのステータスコードコンテナを終了したフィルタリング、awkは最初のフィールドを表示し、grepは、CONTAINERの単語を除外して行を選択します。
代わりに:
docker ps -a --filter 'exited=9' | grep -v CONTAINER | awk '{print $1}'ここでは、docker psは9つのステータスコードコンテナをフィルタリングし、grepはCONTAINERという単語を除いた行を選択し、awkは最初のフィールドを表示します。
一般的には、最初にgrepで選択を行い、最後のステップとしてawkで必要なカラムだけを表示します。論理的には、grepで選択し、最後にawkで結果を表示するという流れの方が良いでしょう。
ステータス9が終了したコンテナを、エラーメッセージを表示させずに削除してみましょう。
実行:
docker ps -a --filter 'exited=9' | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm期待される出力
857cf388b70cSuccess: コンテナが削除され、エラーは表示されません。
ステータス123が終了したコンテナを、エラーメッセージが表示されないように削除してみましょう。
実行:
docker ps -a --filter 'exited=123' | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm期待される出力
8b084d95a2fbSuccess: コンテナが削除され、エラーは表示されません。
実行します。
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9d4163879e17 redis:alpine "docker-entrypoint.s? 10 minutes ago Up 10 minutes 6379/tcp redis 2754c6805252 nginx:mainline-alpine "nginx -g 'daemon of? 10 minutes ago Up 10 minutes 80/tcp nginxnginxとredisだけがまだ動いています。
ステータスのコンテナを削除:作成済み
コンテナが作成された状態で終わってしまうことがあります。これは、コンテナが何かのエラーで実行中の状態に入れなくなったときに起こります。
ここでは、起動時のランフェーズで意図的にエラーを発生させて、作成状態のコンテナを作成してみましょう。
実行:
docker run -d alpine:3.8 <span class=error> zxgarbagez </span>期待される出力
cc00b62dcb5078fed6d9e3fc48a9e5e7a9f3ef11d6722073781c3f5054696889 docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \" <span class=error> zxgarbagez </span>\": executable file not found in $PATH": unknown.実行:
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc00b62dcb50 alpine:3.8 "zxgarbagez" 28 seconds ago Created zealous_colden 9d4163879e17 redis:alpine "docker-entrypoint.s? 17 minutes ago Up 17 minutes 6379/tcp redis 2754c6805252 nginx:mainline-alpine "nginx -g 'daemon of? 17 minutes ago Up 17 minutes 80/tcp nginxzxgarbagezのエラーで作成された状態になってしまいます。
このように作成されたコンテナだけをリストアップしてみましょう。
docker ps --filter status=created期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc00b62dcb50 alpine:3.8 "zxgarbagez" 28 seconds ago Created zealous_coldenstatus=created にあるコンテナをすべて削除してみましょう。
実行:
docker ps --filter status=created | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm期待される出力
cc00b62dcb50削除されたときに表示されるコンテナの名前。
実行します。
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9d4163879e17 redis:alpine "docker-entrypoint.s? 17 minutes ago Up 17 minutes 6379/tcp redis 2754c6805252 nginx:mainline-alpine "nginx -g 'daemon of? 17 minutes ago Up 17 minutes 80/tcp nginxnginxとredisだけがまだ動いています。
ステータスでコンテナを削除します:一時停止
このセクションでは、コンテナを一時停止してから削除を試みます。
Dockerはコンテナ内の全てのプロセスを凍結/一時停止するためにcgroupsフリーザー機能を使用します。
cgroups フリーザー機能を使うと、コンテナ内のプロセスは気づかず、フリーズコマンドを防ぐことも無視することもできません。
実行:
docker run -d --name testme alpine:3.8 /bin/sh -c 'sleep 10m'小さな alpine Linux ディストリビューションを使ってコンテナを起動します。/bin/sh コマンド ( /bin/bash の小型版) を使用しています。sleep コマンド (何もしない) を 10 分間実行します。これで、一時停止できるコンテナが起動しました。
実行:
docker pause testme期待される出力
testmedocker pause showed the name of the container it just paused: testme実行:
docker ps -a期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 637489e9b88d alpine:3.8 "/bin/sh -c 'sleep 1? 14 seconds ago Up 6 seconds (Paused) testme一時停止状態になっていることに注意してください。
以下のコマンドを実行すると、同じ出力リストが得られます。
docker ps --filter status=pausedこのコンテナを削除してみましょう。実行してみます。
docker ps --filter status=paused | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm期待される出力
Error response from daemon: You cannot remove a paused container 637489e9b88d5704b9e677ff26199a9fec41644d4310732943cab0a2c8b0d4a6. Unpause and then stop the container before attempting removal or force remove出力を読んでみてください。実行してコンテナを停止してみましょう。
docker stop testme期待される出力
testmettme が停止したことを示します。
一時停止したいコンテナが複数ある場合は、以下のようにして一気に停止させることができます。
docker ps --filter status=paused | awk '{print $1}' | grep -v CONTAINER | xargs docker container stopこれで一時停止状態のすべてのコンテナが停止します。
これでうまくいったかどうか調べてみましょう。
実行:docker ps --filter status=stopped期待される出力
Error response from daemon: Invalid filter 'status=stopped’明らかに停止状態はありません。コンテナを停止すると終了状態になります。
コンテナの有効な状態の一覧: created, restarting, running, removing, paused, exited, or dead
今度は正しい状態である exited を使って、それがうまくいったかどうかを調べてみましょう。実行してみましょう。
docker ps --filter status=exited期待される出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3e8fb9e2c41d alpine:3.8 "/bin/sh -c 'sleep 1? 3 minutes ago Exited (137) About a minute ago testme成功しました。これが現在終了しているコンテナのリストです。このコンテナIDのリストをdocker container rmに渡して、これらのコンテナを削除してみましょう。実行します。
docker ps --filter status=exited | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm期待される出力
3e8fb9e2c41d成功しました これで、1つだけ終了したコンテナが削除されました。自分で docker ps -a を実行すると、このコンテナがリストに表示されなくなりました。
一時停止していたコンテナは、一時停止した場所で再開できるようになりました。停止しているコンテナは、停止した場所で再起動することはできません。コンテナを再起動すると、最初から始まります。
まとめ: 一時停止したコンテナのプルーニング/削除はできない - 一時停止を解除してからコンテナを停止する必要がある。
終了時にコンテナを削除する
すでに、hello world のコンテナは手動で削除・プルーニングしなければならないことがわかりました。
コンテナを --rm オプションで実行すると、コンテナが終了したときに自動的に削除されます。
これで実践的な体験をしてみましょう。そうすると、便利な --rm オプションを必ず使うことになるでしょう。
以下の3つのコマンドを実行して、3つのhello worldコンテナを作成します。
docker run -d --rm hello-world docker run -d --rm hello-world docker run -d --rm hello-worldを使ってコンテナの一覧を確認してみましょう。
docker ps -a期待される出力。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES終了したhello worldコンテナが表示されていません。rmはこれら3つのコンテナが終了すると自動的に削除します。クリーンアップの必要はありません。
これらのbash aliasesを定義してください。2つ目のaliasを使ってクイックテストを行うことができ、後のクリーンアップの手間を省くことができます。
alias dr='docker run'
alias drrm='docker run --rm'
bash のエイリアスは長いシェルコマンドの短縮版です。その目的は、長いコマンドを入力しないようにすることです。
チュートリアルのクリーンアップ
このチュートリアルはここまでです。
以下のコマンドを実行して、使用しなくなった画像をすべて削除してください。
docker image rm hello-world:latest docker image rm nginx:mainline-alpine docker image rm redis:alpine docker image rm alpine:3.8Dockerの全体的なクリーンアップ
もしかしたら、あなたの開発用 docker サーバーは混乱しているかもしれません。
すべてのコンテナを停止すべきかもしれません。
そんなときは、以下のような方法ですぐに実行できます。
docker stop $(docker ps -a -q) #stop ALL containersdocker ps -a -q builds a list of all container IDs - running and exited.これらのIDをdocker stopに渡します。
すべてのコンテナが停止します。既に終了したコンテナに対してはエラーは表示されません。
すべてのコンテナを削除するには、次のように実行します。
docker rm -f $(docker ps -a -q) # remove ALL containers概要
これで、あなたの仕事にコンテナクリーンアップコマンドを適用して実験することができるようになりました。
安全のためのヒント: 常にコマンドを実行して、選択されたコンテナのリストを表示するようにしてください。その後、docker container rm を実行して、実際にコンテナを削除してください。
grep, awk, xargs はこのチュートリアルで幅広く使われています。これらのツールに慣れていない場合は、チュートリアルを読む価値があることがわかります。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-07-22T13:52:48+09:00
重要なDocker-composeの設定 - Docker Composeのための実践的な演習その2
このチュートリアルでは、Alibaba Cloud上でコンテナを扱う際にDocker Composeを使用して実践的な経験を積むことに焦点を当てています。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
stop_grace_period(猶予期間の終了)
https://docs.docker.com/compose/compose-file/#stop_grace_period より
デフォルトでは、DockerはSIGKILLを送信する前にコンテナが終了するまで10秒待ちます。
SIGKILLを送信する前に、コンテナがSIGTERM(またはstop_signalで指定した停止信号)を処理しない場合に、コンテナを停止しようとしたときにどのくらい待つかを指定します。
これまで私の docker-compose ファイルにはこの設定 ( stop_grace_period ) がありませんでした。そのため、以下のように -t 0 を指定する必要がありました。
docker-compose up -d -t 0-t 0 は、docker-compose がコンテナを終了させる前に 0 秒待機しなければならないことを指定します。タイムアウトのデフォルト値は10秒です。つまり、docker-composeを起動するたびに、コンテナが最終的に終了して再び起動されるまで10秒待たなければならないということです。
docker-compose
ファイルのstop_grace_periodでは、タイムアウト=0の値を指定することができます。を使用して、以下を docker-compose.yml に追加します。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 stop_grace_period: 0s実行します。
docker-compose up -dスリープタイムアウトの値を少し変更して、実行
docker-compose up -dスリープタイムアウトの値を少し変更して、再度実行
docker-compose up -d毎回ほぼ瞬時に再作成されるのを見てください。
stop_grace_periodをデフォルトの10秒に変更します。
docker-compose up -dスリープタイムアウトの値を少し変更して実行
docker-compose up -dスリープタイムアウトの値を少し変更して、再度実行
docker-compose up -dレクリエーションに毎回10秒かかっている様子を見てみましょう。
docker eventsの出力を見てみると詳細がわかると思います。
stop_grace_period. 0s
2018-11-05T14:46:34.968709389+02:00 container kill .... lots of information ... signal=15 2018-11-05T14:46:34.984262101+02:00 container kill .... lots of information ... signal=9stop_grace_period. 10s
2018-11-05T14:47:49.486907072+02:00 container kill .... lots of information ... signal=15 2018-11-05T14:47:59.510613956+02:00 container kill .... lots of information ... signal=9signal=15
SIGTERM は終了信号です。プロセスを終了させますが、クリーンアップルーチンを実行させます。
signal= 9
SIGKILLはキルシグナルです。Kill the process: 直ちに。プロセスはシグナルをキャッチして処理することができず、クリーンアップすることができません。
上で出力されたイベントに基づいて、stop_grace_period. 0sはSIGKILLに行く前にSIGTERMから0.02秒待ちます。
上記のイベント出力に基づいて、stop_grace_period. 10sはSIGKILLになる前にSIGTERMから10秒以上待ちます。
これらのチュートリアルの残りの部分については、すべての docker-compose ファイルに次のように記述されます: stop_grace_period. 0s
注: 本番環境の作業環境に適した stop_grace_period を決定する必要があります。これは、アプリによって異なります。
sysctls
コンテナに設定するカーネルパラメータの設定にはsysctlsを使用します。
カーネルパラメータとは?
Linux ではカーネルパラメータを使ってリソースの制限を設定することができます。カーネルパラメータはrootを含むすべての人に適用されます。
公式のリファレンス情報は https://www.kernel.org/doc/Documentation/sysctl/kernel.txt で確認できます。
Linux シェルで man sysctl を実行すると、実行時にカーネルパラメータを設定する方法が詳しく書かれています。
コンテナを再び起動してみましょう。
docker-compose up -d -t 0を使ってコンテナを入力します。
docker exec -it compose-tuts_alpine_1 /bin/sh表示されたプロンプトで以下の 3 つのコマンドを入力します。これら3つのカーネルパラメータの現在の実際の値が表示されます。
cat /proc/sys/net/core/somaxconn cat /proc/sys/kernel/msgmax cat /proc/sys/kernel/shmmax期待される出力 .
/ # cat /proc/sys/net/core/somaxconn 128 / # cat /proc/sys/kernel/msgmax 8192 / # cat /proc/sys/kernel/shmmax 18446744073692774399 / # exitこの3つの値を変更して、それらの値が適用されているかどうかを確認するためにコンテナを調査します。
docker-compose.yml に以下を追加します。
nano docker-compose.ymlその内容が、
version: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 sysctls: net.core.somaxconn: 512 kernel.shmmax: 18102030100020003000 kernel.msgmax: 4000実行します。
docker-compose up -d -t 0 docker exec -it compose-tuts_alpine_1 /bin/sh表示されたプロンプトで以下の3つのコマンドを入力します。これら3つのカーネルパラメータの現在の新しい実際の値が表示されます。
cat /proc/sys/net/core/somaxconn cat /proc/sys/kernel/msgmax cat /proc/sys/kernel/shmmax期待される出力 .
/ # cat /proc/sys/net/core/somaxconn 512 / # cat /proc/sys/kernel/msgmax 4000 / # cat /proc/sys/kernel/shmmax 18102030100020003000 / # exit見ての通り、これら3つのカーネルパラメータは全て変更されています。
Dockerでは、コンテナ単位でカーネルのパラメータを調整できることがわかりました。
https://docs.docker.com/compose/compose-file/#sysctls より
このオプションは、(バージョン3の)Composeファイルを使用してスウォームモードでスタックをデプロイする場合には無視されます。
namespace付きのsysctls
( 前節からの続きで、重要な見出しを追加しました )
重要:
すべての sysctls がネームスペースになっているわけではありません。
Dockerはホストシステムを変更するコンテナ内の sysctlsの変更に対応していません。現在サポートされているSYSCTLS
kernel.msgmax、kernel.msgmnb、kernel.msgmni、kernel.sem,
kernel.shmall, kernel.shmmax, kernel.shmmni, >kernel.shm_rmid_forcedfs.mqueue.* で始まる Sysctls
net.* で始まる Sysctls
この重要な文章は https://docs.docker.com/compose/compose-file/#sysctls のドキュメントにあるはずです。
fs.file-maxを変更しようとしたところ、このエラーが出ました。
ERROR: for compose-tuts_alpine_1 Cannot start service alpine: OCI runtime create failed: sysctl "fs.file-max" is not in a separate kernel namespace: unknownこれで理解できました: fs.file-max はネームスペースではありません。DockerはHOSTシステムを変更するコンテナ内のsysctlsの変更をサポートしていません。
fs.file-max の変更 (コンテナ内での) は、HOST サーバの設定を変更することになりますが、これは許可されていません。
ネームスペースは Linux 上のコンテナの基本的な側面です。https://en.wikipedia.org/wiki/Linux_namespaces を参照してください。
ネームスペースは、コンテナが孤立したバブル環境で存在することを可能にします。ネームスペースは、コンテナが完全なLinuxディストロであり、サーバ上で単独で動作していると思わせます。
fs.file-max は Linux の機能の一例ですが、現在のところコンテナ内ではネームスペースを分離することができません。
そのため、ネームスペースを持たないカーネルパラメータは HOST サーバ上で調整しなければなりません - その上で実行されるすべてのコンテナに適切なものになるようにしなければなりません。
限界
Ulimit はシェルが利用できるリソース (サイズ、CPU 時間、優先度など) とシェルが起動するプロセスを制御します。
これを使うことで、バグのあるアプリケーションが過負荷をかけてサーバをクラッシュさせないようにすることができます。
Docker のコンテキストでは、コンテナ内で実行されるアプリケーションを制限するためにコンテナ内でこれを使うことができます。
シェルプロンプトでman ulimitを使って公式のドキュメントを読んでください。
ulimitがコンテナ内で実行されることを証明してみましょう。最大プロセス数と最大オープンファイル数を無茶苦茶に低く設定してコンテナを起動してみましょう。
docker-compose.ymlに以下のように追加します。
nano docker-compose.yml # add this contentversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 60171 stop_grace_period: 0s ulimits: nproc: 2 nofile: soft: 2 hard: 4コンテナを起動してみます。
docker-compose up -d -t 0期待される出力 .
Recreating compose-tuts_alpine_1 ... error ERROR: for compose-tuts_alpine_1 Cannot start service alpine: OCI runtime create failed: container_linux.go:348: starting container process caused "open /proc/self/fd: too many open files": unknown予想通り: 開いているファイルが多すぎてエラーになります。コンテナは小さいですが、起動するには4つ以上のファイルを開く必要があります。
nproc ( プロセス数を 1 に変更。両方のnofileの制限を40以上に変更。
再実行します。
docker-compose up -d -t 0これは完璧に起動します(私のCentOS 7サーバで)。
nproc を制限するにはカーネル 4.3 以上が必要です - 私のサーバのカーネルバージョンは 3.10.0-327.el7.x86_64 です。uname -r を実行してカーネルのバージョンを取得してください。
ulimit を設定してみましょう: fsize - 最大ファイルサイズ (KB)
を使用して、以下を docker-compose.yml に追加します。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 60171 stop_grace_period: 0s ulimits: fsize: 10実行します。
docker-compose up -d -t 0 docker exec -it compose-tuts_alpine_1 /bin/sh10MBのファイルを作成して、ファイルサイズの制限である10KBを超えてみましょう。
/ # dd if=/dev/zero of=/tmp/output.dat bs=1M count=10コンテナが存在するだけで、シェルセッションがクラッシュしました。
別の時間に私はエラーメッセージを得ました。
dd if=/dev/zero of=/tmp/output.dat bs=1M count=10 File size limit exceeded (core dumped)Configs
Configs は、コンテナ内のアプリケーションに必要な設定ファイルを宣言します。通常 /etc や F/opt の中にあるような設定ファイルが必要です。
docker-compose secrets は秘密の情報を保存するためのものです。
まず、docker-compose.yml の中で参照できるように、2つの小さな設定ファイルを作成する必要があります。
まず最初の設定ファイルを作成します。
nano config_data '# config data次に、2つ目のconfigファイルを作成します。
nano my_second_config.config '# my_second_config.config の内容ここで、DockerがこのSECOND FILEのみをmy_second_configFという名前のコンフィグとして作成する必要があります。
docker config create my_second_config my_second_config.configこれら2つの異なるConfigは、Configsの2つの異なる使い方をデモします。
docker-compose.yml に以下のように追加します。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 configs: - my_first_config - my_second_config configs: my_first_config: file: ./config_data my_second_config: external: trueトップレベルの configs 宣言 (下の 5 行目) は、このスタック内のサービスに付与される 2 つの config を定義しています。
サービスレベルの config (7 行目から 10 行目あたり) は、コンテナに 2 つの config へのアクセスを許可します。
両方の設定宣言を使用しなければなりません。
my_second_configはexternal: trueと定義されていることに注意してください。これはDockerのconfigオブジェクトとして存在します。
docker-compose upは'configs'設定をサポートしていません。スウォームへのデプロイにはdocker stack deployを使用する必要があります。
docker swarm init docker stack deploy -c docker-compose.yml mystack docker ps -a期待される出力 .
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ab50c7daf979 alpine:3.8 "sleep 600" 14 seconds ago Up 13 seconds mystack_alpine.1.jq3buvzkf2a3hpn7mwb0e43om自動生成されたコンテナ名を取得するために docker ps を実行しなければなりません。
ランダムに生成されたコンテナ名が手に入ったので、それを exec で入力します: コンテナのランダムな配列は異なります。自分のコンテナ名を使って実行してください。
docker exec -it mystack_alpine.1.jq3buvzkf2a3hpn7mwb0e43om /bin/sh期待される出力 .
/ # ls bin lib my_second_config sbin usr dev media proc srv var etc mnt root sys home my_first_config run tmp / # cat my_first_config '# config data / # cat my_second_config '# my_second_config.config contents / # exitこれらの設定は / ディレクトリにマウントされていることに注意してください。
Linux 管理者が config を見つけることができると思われるディレクトリにマウントしましょう。
docker-compose.yml に以下を追加します。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 configs: - source: my_first_config target: /etc/my_first_config - source: my_second_config target: /opt/my_second_config configs: my_first_config: file: ./config_data my_second_config: external: true実行します。
docker stack rm mystack2つの異なるターゲットパスに注意してください。/etc と /opt です。
docker stack deploy -c docker-compose.yml mystack期待される出力 .
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 01156eb13576 alpine:3.8 "sleep 600" 4 seconds ago Up 2 seconds mystack_alpine.1.vg2m0ge161anuoz31c2mdgf1kコンテナに入って、設定が要求されたディレクトリにあるかどうかを調べてみましょう。
docker exec -it mystack_alpine.1.vg2m0ge161anuoz31c2mdgf1k /bin/sh期待される出力 .
/ # ls bin etc lib mnt proc run srv tmp var dev home media opt root sbin sys usr / # cat /etc/my_first_config '# config data / # cat /opt/my_second_config '# my_second_config.config contents / # exitls は設定が / ディレクトリにないことを確認します。
2つの cat コマンドは、設定が要求されたディレクトリの中にあることを示しています。
secrets
secretsは上記で説明したように設定と非常によく似た働きをします。大きな違いは、secretsの内容が暗号化されていることです。
を使って docker-compose.yml に以下を追加してください。
nano docker-compose.ymlversion: "3.7" services: alpine: image: alpine:3.8 command: sleep 600 secrets: - my_secret secrets: my_secret: external: true既存のスタックをすべて閉じます。
docker-compose down -t 0 docker stack rm mystack docker container prune -f Let's create my_secret:echo a secret password | docker secret create my_secret -最後のハイフンは、docker が標準入力 (この場合はエコーテキスト) から読み込まなければならないことを意味します。
ここで docker secret ls を実行すると、秘密がリストアップされています。
docker stack deploy -c docker-compose.yml mystack自動生成されたコンテナ名を取得するためにdocker psを実行する必要があります。
docker ps -aこれでランダムに生成されたコンテナ名を exec で入力することができるようになりました。あなたのコンテナ名を使って実行してください。
docker exec -it mystack_alpine.1.xrgtrrfnwn2qet5pevj5n9 /bin/shwne示されているようにコマンドを実行します。
- df to show /run/secrets/my_secret exist - in tmpfs - in ram. - cat /run/secrets/my_secret ... to see the secret./ # df -h Filesystem Size Used Available Use% Mounted on /dev/mapper/docker-253:1-388628-c16342a3e1f1bfcdcebb82872fa626a5f35a2bea4e535aa9a889069b85c63332 10.0G 37.3M 10.0G 0% / tmpfs 64.0M 0 64.0M 0% /dev tmpfs 492.6M 0 492.6M 0% /sys/fs/cgroup /dev/mapper/centos00-root 12.6G 5.5G 7.1G 43% /etc/resolv.conf /dev/mapper/centos00-root 12.6G 5.5G 7.1G 43% /etc/hostname /dev/mapper/centos00-root 12.6G 5.5G 7.1G 43% /etc/hosts shm 64.0M 0 64.0M 0% /dev/shm tmpfs 492.6M 4.0K 492.6M 0% /run/secrets/my_secret tmpfs 492.6M 0 492.6M 0% /proc/acpi tmpfs 64.0M 0 64.0M 0% /proc/kcore tmpfs 64.0M 0 64.0M 0% /proc/keys tmpfs 64.0M 0 64.0M 0% /proc/timer_list tmpfs 64.0M 0 64.0M 0% /proc/timer_stats tmpfs 64.0M 0 64.0M 0% /proc/sched_debug tmpfs 492.6M 0 492.6M 0% /proc/scsi tmpfs 492.6M 0 492.6M 0% /sys/firmware / # cat /run/secrets/my_secret a secret password / # exit以下のコマンドを実行すると、シークレットそのものが見えなくなります。
docker inspect my_secret[ { "ID": "vjvqnag6nu0p87xc0o94p315g", "Version": { "Index": 386 }, "CreatedAt": "2018-11-06T12:05:40.984748215Z", "UpdatedAt": "2018-11-06T12:05:40.984748215Z", "Spec": { "Name": "my_secret", "Labels": {} } } ]サーバー上のすべてのsecretsのリストを見るには、以下を実行します。
docker secret lsアリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-07-22T12:38:17+09:00
Docker 上の Redash のログのサイズを調べる
Redash を動かしているサーバのディスクが枯渇してきたので、ログが圧迫している可能性を考えたが、Docker で動かしていたので、どこにログがあるのか不明だった。
docker inspect
を使うと、ログの場所がわかる、ということなので、作ったワンライナーが下記。
調べても意外と出てこなかったので、備忘録として残す。docker container ls --format "{{.Names}}" | xargs -tn1 -I{} sh -c "sudo ls -lh \$(docker inspect --format='{{.LogPath}}' {})"
- 投稿日:2020-07-22T11:18:51+09:00
Next.jsのdockerコンテナでホットリロードされないときの解決法
解決法
プロジェクトルートにnext.config.jsを作成する
next.config.jsmodule.exports = { webpackDevMiddleware: config => { config.watchOptions = { poll: 800, aggregateTimeout: 300, } return config }, }実行環境
- win10
- docker-machine
ソースコード
. ├─ .next ├─ node_modules ├─ pages │ └─ index.js ├─ docker-compose.yml ├─ Dockerfile └─ package.jsondocker-compose.ymlversion: '3.3' volumes: node_modules: services: app: build: . container_name: next ports: - '80:3000' restart: always volumes: - '.:/app' - 'node_modules:/app/node_modules' tty: true stdin_open: true# Dockerfile FROM node:12 WORKDIR /app COPY ./package*.json ./ CMD bash -c "npm install && npm run dev"package.json{ "name": "nextjs", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "next", "build": "next build", "start": "next start" }, "author": "", "license": "ISC", "dependencies": { "next": "^9.4.4", "react": "^16.13.1", "react-dom": "^16.13.1", } }pages/index.jsconst Index = () => ( <div> <p>Hello Next.js</p> </div> ) export default Index
- 投稿日:2020-07-22T10:47:49+09:00
node+nodemonのdockerコンテナ
node + nodemon の開発用コンテナを作成した。実行環境はwin10とdocker-machine
. ├── app.js ├── docker-compose.yml ├── Dockerfile ├── package-lock.json ├── package.json └── node_modules#Dockerfile FROM node:12 WORKDIR /app # ホストのpackage.jsonとpackage-lock.jsonを # コンテナの/appにコピー COPY ./package*.json ./ CMD bash -c "npm install && npm run dev"docker-compose.ymlversion: '3.3' volumes: node_modules: services: app: build: . container_name: node ports: - '80:8081' restart: always volumes: # ホストのdocker-compose.ymlがあるディレクトリを # コンテナの/appマウントする - '.:/app' # ただしnode_modulesだけ除外するためnode-mudulesボリュームを # コンテナの/app/node_modulesにマウントする # コンテナ内でnpm install してもホストのnode_modulesは空のまま - 'node_modules:/app/node_modules' # 下2行はdocker run コマンドの-itオプションに相当する # 無いとコンテナが停止してしまう tty: true stdin_open: truepackage.json{ "name": "hoge", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "start": "node ./app.js", "dev": "nodemon -L ./app.js" }, "dependencies": { "express": "^4.16.1" }, "devDependencies": { "nodemon": "^2.0.4" }, "author": "", "license": "ISC" }以下のようにしてDockerfileで
npm start
するとnodemonは機能しなかった。start
キーではダメ。さらに-Lオプションが必要。"scripts": { "start": "nodemon ./app.js" }起動コマンドなど
コンテナ起動
docker-compose up -d
node_modulesボリュームは自動で作成される。project_node_modulesという名前になる。docker-machineのIPアドレスでブラウザからnodeサーバーにアクセスできる
nodemonが機能してることを確認する
docker-compose logs -f
または
docker logs node -f
コンテナ削除
docker-compose down --rmi all
--rmi all でイメージも削除される
node_modulesボリュームを削除
docker volue rm project_node_modules
ボリューム名を確認
docker volume ls
docker-machineのIPを調べる
docker-machine ls
または
docker-machine ipdocker-machine ip default
- 投稿日:2020-07-22T10:24:43+09:00
MacでNodedock + NUXTの開発環境を作る
目的
- NodedockでDockerの開発環境つくる
- 新規にNUXTプロジェクトを作る
- ブラウザで表示する
ちなみに、経緯としては
久しぶりにMacでyarnでnuxtを新規にcreateして…いつもの流れで構築すると、バージョン周りでyarnコマンドがエラー吐きまくって解決に時間かけるのも煩わしかったので、dockerでサクッと作れないかなと思い立ったのが経緯。バージョン
Host
- macOS Catalina 10.x
- git version 2.24
- Docker version 19.03
- docker-compose version 1.25
Guest
- create-nuxt-app 3.1.0
- node 10.20.1
- yarn 1.22.4
参考サイト
NodedockでDockerの開発環境つくる
作業用ディレクトリ作成
mkdir sample-project cd sample-projectNodedockをCloneする
git clone https://github.com/nodedock/nodedock.git.envを作成
cd nodedock cp env-example .env.envを編集
- NODE_VERSION=10.7.0 - NGINX_HOST_HTTP_PORT=80 + NODE_VERSION=10.20.1 + NGINX_HOST_HTTP_PORT=38080nginxの設定追加
cp nginx/sites/app.conf.example nginx/sites/app.conf- server_name app.test; - root /var/www/app; + server_name node.test + root /var/www/<project name>;hosts設定追加
vi /etc/hosts
127.0.0.1 node.testdocker起動
docker-compose up -d nginx mysql # 再ビルドする場合 docker-compose build --no-cache nginx mysql docker-compose up -d nginx mysqlworkspaceにログイン
docker-compose exec workspace bash
バージョン確認
※執筆時点のバージョンですroot@xxxxx:/var/www# node -v v10.20.1 root@xxxxx:/var/www# yarn -v 1.22.4 root@xxxxx:/var/www# npm -v 6.14.4新規にNUXTプロジェクトを作る
workspaceにログイン
※ログイン済の場合はスキップdocker-compose exec workspace bash
yarnでnuxtプロジェクトを新規作成
※npmの場合は公式サイトを参照yarn create nuxt-app nuxt-project各設問について
下記記事で詳しく解説しています
Nuxt.jsで多言語化デビューしよう!
Project name
... プロジェクト名 ※未入力でEnterした場合は()内の名称になる
Programming language
... 言語選択。動的型付けならJavascript、静的型付けならTypescript
Package manager
... パッケージ管理ツール選択。NPMかYarn(Yarn推奨)
UI framework
... UIフレームワーク選択。後から追加可能。
Nuxt.js modules
... モジュール選択。
Linting tools
... 静的解析ツール選択。
Testing framework
... テストフレームワーク選択。
Rendering mode
... レンダリングモード選択。
Deployment target
... デプロイ対象。サーバーサイドならServer、サーバーレスならStatic
Development tools
... デプロイツール。参考までに。
サーバーサイドのアプリケーションを作りたいので今回の設定はこんな感じ。✨ Generating Nuxt.js project in nuxt-project ? Project name: nuxt-project ? Programming language: TypeScript ? Package manager: Yarn ? UI framework: None ? Nuxt.js modules: ? Linting tools: ESLint ? Testing framework: Jest ? Rendering mode: Universal (SSR / SSG) ? Deployment target: Server (Node.js hosting) ? Development tools:下記が表示されればインストール完了
? Successfully created project nuxt-projectアプリケーション起動
cd <project name> nuxt build nuxt start下記URLにアクセス
page/index.vueの内容が表示されていればOK【余談】
記事振り返ってみたら、hosts追加したのに使ってなかったです。。
ドキュメントルートで読み込まれるファイルが見当たらなかったので、今度時間作ってちゃんと仕組み理解して更新します。
- 投稿日:2020-07-22T08:40:53+09:00
Dockerのデータの”保存”する仕組みについて理解した話
1. はじめに
dockerやdocker-composeを使って、チームで使うサービス(re:dash)を運用したら、
バージョンアップとかガンガンできるだろうし、バックアップもリストアも自由自在ヒャッハーできるしょ!
と思って使いはじめたが、やりたいことができずきハマった、データ保存先について整理した記事です。”保存”に特化しているため、dockerがほかの仮想マシンと比較してどうかなどの、メリットとデメリットなどを記載はしません。だって面倒くry。
この記事を読むと、dockerのデータを”保存”しているのか、イメージを理解できようになります(たぶん)。
2. dockerがデータを"保存"するモノとは
データを”保存"する「イメージ」「ボリューム」「コンテナ」の概念について、まとめます。
概念が違うものなので、並べることが適切ではないかもしれませんが、保存を理解するためには必要なので、並べて書きます。※ Dockerfile, docker-compose.yml と記載したものは設定ファイル名の例です。
実際には変更が可能なため、正しくありませんが便宜的に上記表現で記載しています。2.1 イメージ
Dockerfileで定義された、「docker image」で管理される領域、またはDocker Hubなどのサービス可能に登録されたものです。
どのような構成、何をインストールしておくか、といったことを”保存”できます。2.2 ボリューム
データを"保存"するデータ領域のことを指します。ボリュームといっても、コンテナ内部(Dockerfile volumeコマンドなど)と外部マウント(docker run -v xxx:yyyy)の2つのことが混同されて記述されている記事があるため、注意が必要です。
外部マウントのボリュームは、dockerサービス内で定義されたボリューム(docker volume createや他のコンテナのボリュームなど)と、dockerのホストのデータ領域の、いずれかを指定することができます。
簡単な図にまとめると、以下のようなイメージです。
※注意 正確にはボリュームをマウントする指示をせずに実行した場合には、dockerのvolumesに実体が作られ、--rmオプションなどがついてると自答削除できるので、図ではわかりやすさのため、コンテナ内にあるように歪曲して記載しています。2.3 コンテナ
イメージに対して「docker run」を実行して作られる、コンテナとよばれるインスタンスのことを指します。
このインスタンスには、起動中、停止中の状態をもち、docker start, docker stopなどで、開始、停止をコントロールできます。
起動中の場合に、イメージで作ったサービスが利用できるようになります。起動時に、マウントする先を明示的におこなっていない場合、コンテナで作成されたボリュームは、起動したコンテナが削除されるまで”保存”できます。その状態で、うっかり、「docker rm コンテナ」としてしまうと、
保存されたデータが削除され、泣くことができます。3 データの保存先について(考察)
サービスとして提供するのであれば、dockerのボリューム領域(docker volume createで作った領域)か、ホストのデータ領域を使うのが賢明だと思います。
ただし、dockder for windows (desktop 2.3.0.3, engine 19.03.8, compose 1.25.5)では、
ボリュームに対して権限を設定しようとするとうまくいかない不具合があるため、アプリによっては、dockerのボリューム領域を使う必要があります(postgresの公式イメージのdataフォルダなど)。そのため、現状でバックアップまで考えた運用については、ホスト領域とdockerのボリューム領域をマウントして、コピーするだけの仮想コンテナを作ってあげるなど工夫が必要そうです。
※ 実はそれでも権限周りはいけてなく、現状ではlinuxの上に構築するほうが無難です。4 おわりに
dockerについて勉強をはじめて、1か月たたない初心者なので、もし間違いがあったら、指摘をお願いします。
- 投稿日:2020-07-22T01:04:49+09:00
dockerで作るnuxt.jsの開発環境
環境
docker desktop for windows(wsl2)
実装
Dockerfile
FROM node:12.18.2-alpine RUN apk update && \ npm install -g npm && \ npm install -g create-nuxt-app ENV HOST 0.0.0.0 EXPOSE 3000node.jsの最新安定板のコンテナイメージでnpmの更新とcreate-nuxt-appをインストールしています。それからホスト側からアクセスできるようにします。
docker-compose.yml
version: '3' services: web: build: . ports: - "3000:3000" working_dir: "/usr/local/src" volumes: - ".:/usr/local/src" - node_modules_volume:/usr/local/src/first-app/node_modules tty: true volumes: node_modules_volume:Dockerfileと同じディレクトリ内に配置して使います。
ポートフォワーディングとデータ永続化、コンテナの起動を維持するためのtty: trueだけを記述したシンプルな構成です。あとは、node_module用にVolumeを作成します。これがあるのと無いのとでは実行速度に天と地の差がありました。ビルド&起動
$ docker-compose build $ docker-compose upすると、dockerのダッシュボードから確認できるようになるので、cliからコンテナの中に入ります。
アプリケーション作成
/usr/local/src # npx create-nuxt-app first-app create-nuxt-app v3.1.0 ✨ Generating Nuxt.js project in first-app ? Project name: first-app ? Programming language: JavaScript ? Package manager: Yarn ? UI framework: Vuetify.js ? Nuxt.js modules: Axios, Progressive Web App (PWA) ? Linting tools: ESLint, Prettier, Lint staged files, StyleLint ? Testing framework: None ? Rendering mode: Universal (SSR / SSG) ? Deployment target: Server (Node.js hosting) ? Development tools: jsconfig.json (Recommended for VS Code) . . . ? Successfully created project first-nuxt-app To get started: cd first-nuxt-app yarn dev To build & start for production: cd first-nuxt-app yarn build yarn start To test: cd first-nuxt-app yarn testnuxtの既成レイアウトを使いたい
https://vuetifyjs.com/ja/getting-started/pre-made-layouts/
この中のBaselineが使いたいのでlayouts/default.vueを変更(コピペ)cd first-nuxt-app yarn dev . . . . 82:10 error Insert `⏎` prettier/prettier ✖ 16 problems (15 errors, 1 warning) 15 errors and 0 warnings potentially fixable with the `--fix` option.詳しいことはわかりませんがprettierがエラーをだした。下記コマンド実行後サーバー再起動。
https://stackoverflow.com/questions/52571675/nuxt-js-module-error-from-node-modules-eslint-loader-index-jsnpx prettier --write "**/*.{vue,js}"ホットリロード
サーバー再起動するが面倒なのでホットリロードの設定をつけます。
nuxt-config.jsにてmodule.exports = { ... watchers: { webpack: { poll: true } }Waiting for file changes 15:57:50 ℹ Memory usage: 472 MB (RSS: 595 MB) 15:57:50 ℹ Listening on: http://172.21.0.2:3000/動きました!