Table of Contents
モチベーション
- Dockerのライフサイクルについてまとめておきたい
- Dockerfileの書き方についてまとめておきたい
- docker-composeについてまとめておきたい
Dockerのライフサイクル
docker run
で,Dockerイメージを元にコンテナを起動する.docker stop
で,コンテナを停止する.docker commit
で,停止中のコンテナを新たなDockerイメージとしてとっておく.docker save/load
で,Dockerイメージを持ち運ぶ.docker start
で,停止中のコンテナを再開する.docker rm
で,停止中のコンテナを破棄する.docker rmi
で,Dockerイメージを破棄する.
Dockerイメージを用意する
- Dockerfileの書き方
docker build -t <image name>:<tag> <Dockerfileがあるディレクトリ>
によりDockerイメージがつくられる<tag>
にはimageのversionを設定するのが一般的.<tag>
を省略した場合はlatest
とされる.
docker pull <image name>
でDockerイメージをもってくることができる.- DockerイメージはDocker Hubにて検索できる.
docker images
で手元にあるDockerイメージ一覧を表示する.docker images -q
により,DockerイメージID一覧を表示する.
Dockerイメージを元に,コンテナを立ち上げる
docker run -it --name <container name> <image name>:<tag> <command>
<image name>:<tag>
から<container name>
という名前のコンテナを立ち上げ,コンテナ内で<command>
を実行する.-i
はホストからコンテナへの標準入力を繋げるためのもの.-t
はコンテナからホストへの標準出力を繋げるためのもの.-h
オプションによって,ホスト名を指定できる.-d
オプションによって,コンテナをバックグラウンドで実行できる.-p <host>:<container>
オプションによって,ホストのポートとコンテナのポートをつなげる.この時,iptablesが書き換えられ,ホスト側のポートがWANに曝されるので注意.-p
でなく,--expose <port>
フラグを指定すると,リンクしたコンテナから<container name>:<exposed port>
でアクセスすることができる.また,iptablesは変更されない.
--rm
フラグによって,コンテナがstopしたあとはコンテナを削除するようにする.--privileged
フラグによって,コンテナ内からホストのデバイスにアクセスすることができる.セキュリティには注意する.--device
フラグや--cap-add
フラグによってデバイス単位で細かくアクセス権限を制御することができる.
--link <container>:<nickname>
を指定することで,<container>
へアクセスする際のホスト名として利用できる.- 例えば,hogeという名前のコンテナが立ち上がっている環境で,
--link hoge:hg
を指定して新たなコンテナを立ち上げたとすると,そのコンテナからはcurl http://hoge
というような形でアクセスすることができる.
- 例えば,hogeという名前のコンテナが立ち上がっている環境で,
- Dockerイメージによっては,ずっと起動するものもあれば,
<command>
を一発実行してstopするものもある.<command>
に/bin/sh
を指定し,コンテナ内にshを立ち上げることで,コンテナを立ち上げたままにしておくことが多い.
docker ps
- 起動中のコンテナ一覧を表示する
docker attach <container>
- コンテナにアタッチする.アタッチ後の振る舞いはDockerイメージによって異なり,コンテナの標準入出力が可能になる場合もあれば,何も起きない場合もある.
- アタッチしている状態で,
ctrl+p
しctrl+q
すると,コンテナからデタッチすることができる.
docker exec -it <container> <command>
- 起動中のコンテナにコマンドを流し込むことができる.
<command>
に/bin/sh
を指定してコンテナ内にシェルを立ち上げることで,コンテナ内で作業することができる.
DockerコンテナのPID=1問題
docker run
で指定した<commnad>
は,PID=1のプロセスとして実行される.PID=1なプロセスはカーネルから特別扱いされるため,プロセス自体がシグナルをハンドルするように実装されていなければ,シグナルは無視されてしまう.
例えば,docker kill -s TERM <container>
を実行することで,PID=1のプロセスにSIGTERMを投げることができるが,PID=1のプロセスのシグナルのハンドルの仕方によって振る舞いが異なる.
PID=1のプロセスがシグナルをハンドルするように実装するのもよいが,プロセスがPID=1以外で実行されれば,シグナルを素直に受け付けるので,<command>
で指定したプロセスをPID=1以外にするためには,docker run
を実行する際に,--init
オプションを指定すると良い.
# docker run -it centos bash
[root@a31d57ca765c /]# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 1.5 0.1 12020 3348 pts/0 Ss 13:38 0:00 bash <======== `bash`がPID=1で実行されている
root 14 0.0 0.1 47508 3520 pts/0 R+ 13:38 0:00 ps -aux
# docker run -it --init centos bash
[root@52ec324240f8 /]# ps -axu
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 1.0 0.0 996 4 pts/0 Ss 13:39 0:00 /sbin/docker-init -- bash
root 7 0.0 0.1 12020 3336 pts/0 S 13:39 0:00 bash <======== `bash`がPID=1以外で実行されている
root 16 0.0 0.1 44596 3388 pts/0 R+ 13:39 0:00 ps -axu
起動中のコンテナを停止させる
docker stop <container>
<container>
を停止する.
docker ps -a
- 起動中または停止しているコンテナの一覧を表示する.
docker ps -a -q
で,コンテナIDの一覧を表示する.
停止したコンテナを立ち上げる
docker start <container>
コンテナをrestartさせる
docker restart <container name>
で,docker stop
とdocker start
をまとめて実行してくれる,
停止中のコンテナをDockerイメージとして保存する
docker commit <container> <image name>:<new tag>
- 停止中の
<container>
から,<image name>:<new tag>
というDockerイメージを作成する.
- 停止中の
Dockerイメージをtarで固めて持ち運ぶ
docker save <image name>:<tag> > <filename>
で<filename>
に<image name>:<tag>
を書き出すdocker load < <filename>
で読み込むdocker images
でイメージが読み込まれたことを確認docker run -it <filename>
停止しているコンテナを破棄する
docker rm <container>
- 停止中のコンテナは,いつでも再開できるようにキャッシュされてるので,使わなくなったコンテナは
docker rm
で破棄するようにする. docker rm -f
で強制破棄.docker rm -f 'docker ps -a -q'
により,すべての停止中のコンテナを強制破棄することができる.
- 停止中のコンテナは,いつでも再開できるようにキャッシュされてるので,使わなくなったコンテナは
ローカルのDockerイメージを破棄する
docker rmi <image>
docker rmi 'docker images -q'
により,全てのDockerイメージを破棄する.
コンテナとホスト間でファイルをコピーする
docker cp <container>:<source@container> <target@host>
- コンテナからホストにファイルをコピーする
docker cp <source@host> <container>:<target@container>
- ホストからコンテナにファイルをコピーする
コンテナ内でstdout/stderrされたものを外部から見る
docker logs <container>
-f
オプションでリアルタイムで表示するログ自体は
/var/lib/docker/containers/<container id>/<container id>-json.log
にあるロギング情報の確認
docker info --format '{{.LoggingDriver}}'
- 現在設定しているロギングドライバーを確認する
docker inspect -f "{{.LogPath}}" <container name>
- あるコンテナのstdout/stderr出力を保存している先を確認する
Docker for Mac
Linuxでは,Dockerエンジンをホスト上で直接実行しているが,Docker for Macでは,Mac上にVMを立ち上げてその上でDockerエンジンを実行している.
例えば,docker volume ls
でvolume名を取得し,そのvolumeがmountされている場所をdocker volume inspect <volume name>
で確認すると,以下のようなMountpointを取得することができる.ただし,MountpointはMac上には存在せず,VMからみたパスである.
$ docker volume ls
DRIVER VOLUME NAME
local xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
...
$ docker volume inspect xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[
{
"CreatedAt": "2019-12-21T05:10:05Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/_data",
"Name": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"Options": null,
"Scope": "local"
}
]
Dockerfileの書き方
Dockerfileとは,docker build
のための手順書のようなもの.Dockerfileを元にオリジナルのDockerイメージをつくることができる.
FROM nginx:latest
ENV HOGE FUGA
ARG AHO=DEFAULT
RUN apt-get update && \
apt-get install -y certbot python-certbot-nginx && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
echo $AHO
WORKDIR /workspace
ADD nginx.conf /etc/nginx/
ADD default.conf /etc/nginx/conf.d/
EXPOSE 80 443
FROM
でベースとなるDockerイメージを指定する- DockerイメージはDocker Hubにて検索できる.自分でつくったDockerイメージを指定することも可能.
<tag>
を指定しない場合はlatest
なイメージをもってきてくれる.
ENV
で環境変数を設定するRUN export HOGE=FUGA
としてもコンテナ内の環境変数には反映されない.ENV HOGE FUGA
またはENV HOGE=FUGA
とする必要がある.
ARG
で指定した変数は,docker build
コマンドの--build-arg
で任意に変更することができる- 例えば
--build-arg AHO=TEST
を指定すると,RUN
でecho $AHO
が指定されてるので,build時にTEST
と表示される.--build-arg
を指定しない場合はDEFAULT
と表示される.
- 例えば
RUN
にコンテナで実行したいコマンドを指定するWORKDIR
でホストと共有するディレクトリを設定するADD <src> <dest>
でホストの<src>
ファイルをコンテナ内の<dest>
にコピーするEXPOSE
でコンテナの特定のポートを開けておく.docker run -p
時にホストのポートとコンテナのポートを紐付けることでアクセス可能になる.- より細かいことはDockerfile リファレンスを参照する.
docker-compose.ymlでコンテナを複数立ち上げる
複数のコンテナをまとめて立ち上げたいときは,docker-composeを使う.
docker-compose.ymlを書く
version: '3'
services:
nginx:
image: nginx:latest
ports:
- 8080:80
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./www/html:/var/www/html
depends_on:
- php
php:
build:
context: ./php
args:
- TZ=${TZ}
container_name: php-fpm
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
- ./www/html:/var/www/html
environment:
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_DATABASE=${DB_NAME}
- DB_USERNAME=${DB_USER}
- DB_PASSWORD=${DB_PASS}
- TZ=${TZ}
depends_on:
- db
db:
image: mysql:5.7
expose:
- 9999
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
environment:
- MYSQL_DATABASE=${DB_NAME}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASS}
- MYSQL_ROOT_PASSWORD=${DB_PASS}
- TZ=${TZ}
- docker-compose.yml内の
${XXX}
には,ホストの環境変数が適用される. version
は2020年8月時点では3
.詳しくは,Compose file version 3 reference- コンテナ毎にサービス名をつける.
build
またはimage
を指定する- DockerfileからDockerイメージを作成し,コンテナを立ち上げたい場合は,
build
のcontext
にDockerfileがあるディレクトリへのパスを指定する.build
とimage
の両方を指定した場合は,ビルドされたDockerイメージの名前がimage
で指定したものになる. - Dockerイメージからコンテナを立ち上げたい場合は,
image
に<image name>:<tag>
を指定する. args
で,DockerfileのARGに渡すものを指定できる.
- DockerfileからDockerイメージを作成し,コンテナを立ち上げたい場合は,
container_name
に,任意のコンテナ名を指定する.logging
に,コンテナのstdout/stderr出力の保存方法を指定するdriver
には,json-file
の他,syslog
なども指定できるoptions
にログローテートの設定を指定できる.
tty: true
により,docker run
の-it
オプションに相当する設定がされる.volumes
には<ホスト側のパス>:<コンテナ内のパス>
を指定する.これにより,ホスト側のディレクトリがコンテナ内のディレクトリと共有される.environment
には,コンテナ内の環境変数を指定する.ports
には<ホスト側のポート番号>:<DockerfileでEXPOSEしたポート番号>
を指定する.iptablesが変更させるので,ホスト側のポートが外部に曝されるので注意.expose
にポートを指定することで,リンクしたコンテナから<container name>:<exposed port>
でアクセスすることができる.iptablesは変更しない.links
には<サービス名>:<コンテナ内からみたサービスのホスト名>
を指定する.depends_on
には,サービスの起動に必要な別のサービスを指定する.これにより,コンテナが起動する順序が保証される.depends_on
を指定すると,links
を指定する必要はなさそう.- 起動する順序は保証されるが,そのコンテナがアクティブかどうかは
depends_on
で保証されないので,wait-for-it.shなどで細かく制御する必要がある.
- 起動する順序は保証されるが,そのコンテナがアクティブかどうかは
- 詳しくはCompose ファイル・リファレンスを参照する.
docker-compose.ymlを元にコンテナを立ち上げたり止めたりする
docker-compose build
- docker-compose.yml内の各サービスの各Dockerイメージを用意する.
docker-compose up -d
- docker-compose.yml内の各サービスの各コンテナを起動する.
docker-compose ps
- docker-compose.ymlに紐付いた,起動中のコンテナ一覧を表示する.
docker-compose stop
- docker-compose.ymlに紐付いたすべてのコンテナを停止する.