Docker in Action を読む - 1: コンテナ、コマンドの実行
Docker に入門した(n 回目)。docker run などの基本的なコマンドを実行した。
Docker in Action を読みながらメモを取った。
コンテナの構築に使われる重要な特徴
- PID namespace
- UTS namespace
- MNT namespace
- IPC namespace
- NET namespace
- USR namespace
- chroot syscall
- cgroups
- CAP drop
- Security models
Docker を動かす
docker run --detach --name web nginx:latest
docker run -d --name mailer dockerinaction/ch2_mailer
docker run nginx:latest
で最新の NGINX イメージをダウンロードした後、NGINX コンテナを実行する。
すでにダウンロード済みならダウンロードはしない。
docker run
するたびに新しいコンテナが作成される。
Docker run reference | Docker Documentation
Detached
--detach (-d)
をつけてコンテナを起動するとバックグラウンドでプログラムが実行され、ルートプロセスが終了した時点でコンテナが終了する。
デーモンやサービスと呼ばれるプログラムは --detach
で実行するのに適している。
Interactive containers
docker run --interactive --tty --link web:web --name web_test busybox:1.29 /bin/sh
このコマンドを実行すると、コンテナの内部でシェルコマンドを実行できる状態になる。
Docker run reference | Docker Documentation
-t : Allocate a pseudo-tty
-i : Keep STDIN open even if not attached
--interactive
はターミナルにアタッチされなくなるまで標準入力を開いたままにするオプション。--tty
はコンテナに仮想的なターミナルを割り当てるオプション。--tty
を指定して起動することで、コンテナへの入力やコンテナからの出力がターミナルで見れるようになる。
pseudo-tty
Pseudoterminal - Wikipedia
In some operating systems, including Unix and Linux, a pseudoterminal, pseudotty, or PTY is a pair of pseudo-device endpoints (files) which establish asynchronous, bidirectional communication (IPC) channel (with two ports) between two or more processes.
Pseudoterminals (pseudo-TTYs) are used by users and applications to gain access to the shell. A pseudo-TTY is a pair of character special files, a master file and a corresponding slave file. The master file is used by a networking application such as OMVS or rlogin. The corresponding slave file is used by the shell or the user's process to read and write terminal data.
とりあえずシェルへアクセスするのに使われることはわかった。
起動したコンテナの中で wget -O - http://web:80/
を実行すると "Welcome to nginx!" ページの html が取得できる。
Legacy container links を使わないようにする
Legacy container links | Docker Documentation
--link
フラグをつけて実行すると、他のコンテナと通信することができる。
--link
フラグは古い機能で、代わりに user-defined networks の利用が勧められている。
--link
を使わずに上記で実行した wget
までやってみる。
link なしでの実行
link
フラグをつけないで実行し wget
を実行すると html が取得できない。
/ # wget -O - http://web:80/
wget: bad address 'web:80'
ネットワークの作成
docker network create dia-net
で dia-net
という名前の user-defined bridge network を作成する。
コンテナを接続する
docker network connect dia-net web
wget を実行する
docker run -it --network dia-net --name web_test busybox:1.29 /bin/sh
でネットワークを指定してコンテナを実行し、wget -O - http://web:80/
を実行すると html が取得できた。
コンテナを見る
実行中のコンテナは docker ps
で確認できる。-a
フラグを立てると実行していないコンテナも含めて表示する。
docker inspect CONTAINER
でコンテナのメタ情報が出力できる。--format
オプションで出力する値を指定できる。
ログは docker logs <コンテナ名>
で見れる。また、--follow (-f)
フラグを立てることで、停止するまで新しく来たログを次々表示することができる。
PID namespace
docker run -d --name namespaceA busybox:1.29 /bin/sh -c "sleep 30000"
docker run -d --name namespaceB busybox:1.29 /bin/sh -c "nc -l 0.0.0.0 -p 80"
docker exec namespaceA ps
docker exec namespaceB ps
docker exec | Docker Documentation
docker exec CONTAINER COMMAND
は実行しているコンテナでコマンドを実行する。
ps
で現在実行しているプロセスを表示すると、docker run
で指定したコマンドの PID はともに 1 であることが確認できる。
各コンテナは ID 空間を共有しない。
docker run --pid host busybox:1.29 ps
--pid host
を指定することでホスト側の PID 名前空間を使うことができる。
単に ps
を実行するだけだと
PID USER TIME COMMAND
1 root 0:00 ps
のように ps
のみが表示されるが、ホスト側の PID 名前空間を使って ps
するとプロセスが大量に表示される。
Software conflict
docker run -d --name webConflict nginx:latest
docker exec webConflict nginx -g 'daemon off;'
NGINX コンテナを実行したあと、さらにコンテナ内で nginx -g 'daemon off;'
を実行する。
nginx -g 'daemon off;'
Command-line parameters
-g
は global configuration directives を設定するパラメータである。
Core functionality
daemon on | off;
は以下のように説明されている。
Determines whether nginx should become a daemon. Mainly used during development.
daemon off
にするとフォアグラウンドで実行される。
今回はすでに NGINX を実行しているため、
2021/11/29 10:04:47 [emerg] 35#35: bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
というメッセージが表示される。Port conflict が起こって 2 番目のコマンドが失敗している。
docker run -d --name webA nginx:latest
docker run -d --name webB nginx:latest
このように、別々のコンテナで実行すればポートが衝突することなくサーバが立てられる。
衝突を避ける
docker create --cidfile web.cid nginx
docker create
はコンテナを作成するだけで実行はしない。
--cidfile
はコンテナ ID をファイルに書き出す。
すでにファイルが存在している場合、コンテナは作成されない。
Environment-agnostic systems を構築する
Environment-agnostic は環境に依存しない、とらわれないことを意味していると思う。 似た表現として Platform-agnostic というものがあり、複数のプラットフォームでプロダクトが実行できることを示している。
Environment-agnostic systems の構築を助ける、Docker が持つ特徴として以下が挙げられる。
- Read-only filesystems
- Environment variable injection
- Volumes
Read-only filesystems
docker run -d --name wp --read-only wordpress:5.0.0-php7.2-apache
を実行し、docker logs wp
でログを見ると以下のように出力された。
noy72@noy72 docker-in-action % docker logs wp
WordPress not found in /var/www/html - copying now...
Complete! WordPress has been successfully copied to /var/www/html
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
Wed Dec 1 13:49:01 2021 (1): Fatal Error Unable to create lock file: Bad file descriptor (9)
lock file の生成に失敗していることがわかる。コンテナが読み込み専用のため、lock file の書き込みに失敗している。
docker run -d --name wp_writable wordpress:5.0.0-php7.2-apache
--read-only
フラグをつけずに実行するとエラーを起こさずに実行できる。
書き込まれたファイルがどれなのかを調べるのには docker container diff CONTAINER
が使える。
noy72@noy72 docker-in-action % docker container diff wp_writable
C /run
C /run/apache2
A /run/apache2/apache2.pid
--volume
フラグを使うと、書き込み可能なホストのディレクトリをマウントすることができる。--read-only
フラグと併用すると、指定した一部のディレクトリだけ書き込める状態にできる。
tmpfs
tmpfs - Linux技術者認定 LinuC | LPI-Japan
tmpfsはUnix系OSにおける一時ファイルのためのファイルシステム名。
揮発性のディレクトリ?
docker run | Docker Documentation
docker run
の --tmpfs
フラグを使うことでコンテナに tmpfs をマウントできる。
MySQL と WordPress を繋げる(途中まで)
docker run -d --name wpdb -e MYSQL_ROOT_PASSWORD=ch2demo mysql:5.7
docker run -d --name wp3 -p 8000:80 --read-only -v `pwd`/run/apache2:/run/apache2 --tmpfs /tmp wordpress:5.0.0-php7.2-apache
docker network create ch2
docker network connect ch2 wpdb
docker network connect ch2 wp3
M1 Mac だと MySQL の起動ができないので --platform linux/x86_64
を追加して docker run
する。
--env (-e)
は環境変数を設定する。
Restart
--restart
フラグで restart policy (コンテナが終了したときに再起動する条件)を設定できる。
感想
Docker の知識がなさすぎたのでここまででも十分学びになっている。
英語で書かれているので読めているようで読めていない。サンプルコード(コマンド)を実行して雰囲気で読み進めている。
日々膨大な技術情報に接する環境にいるわけですから、限られた時間の中で正確に英文の技術情報を読み解かないといけません。英文法のスキルが足りないのは致命的です。「なんとなく」英文を読んでいるので、正確に内容を読めたかどうか英文法に従って客観的に自分でチェックできない。おそらく学生時代からの勉学の積み残しだと思われます。
(中略)
英語がちゃんと読めるようになって始めて自分の専門的技術力を高めるスタート地点に立てるのです。