Docker とは、指定したパッケージなどを持つ環境(=コンテナ)で、指定したコマンドの実行結果を再現するソフトウェアです。
初めて Docker を学ぶ時は、以下の3つがわからなかったので、本記事に書き残します。
- Docker の利点や使う理由
- Docker の操作方法
- Dockerfile, docker-compose
Docker の利点・使う理由
Docker を利用する利点は主に次の3つです。
パッケージの競合を回避
例えば、次の依存関係がある場合、どちらかのパッケージがインストールできません。
Docker では、ソフトウェア X のバージョン 1.0 と 2.0 の2つの環境(=コンテナ)を用意することで、パッケージの競合を回避可能です。
複数のホストを用意するのが容易
例えば、ロードバランサーやクラスターの検証をする場合、複数のサーバーが必要です。
この時、1つのサーバーに複数のコンテナを作成することで、1つのサーバーで検証できます。
以下の記事では、「ロードバランサー」+「Web サーバー3台」の合計4つのコンテナを1つのサーバーで稼働させる方法を紹介しています。
環境の移行が容易
Docker では、以下の2つを Dockerfile と呼ばれるファイル形式で保存できます。
- 「パッケージを指定した環境(=コンテナ)」
- 「実行するコマンド」
そのため、Dockerfile ファイルを渡すだけで、他のコンピュータに環境を移行できます。
(※「A さんの PC では動くが、 B さんの PC では動かない」という状況を回避できます。)
Docker をインストール
Docker を利用するために、まずはインストールをします。
- Docker をインストール
- sudo systemctl start docker
- docker --version
Docker version 19.03.13-ce, build 4484c46
- sudo usermod -a -G docker `whoami`exit
Docker の使い方
Docker を初めて使う時、ググるキーワードがわからなかったり、1つ1つ調べるのが大変です。
そのため、本記事では上から順にコマンドを入力することで Docker の操作を理解できる文章構成としました。
Docker イメージの取得 pull
Docker コンテナは、Docker イメージと呼ばれるものから作成します。
リポジトリから Docker イメージを取得する方法は以下のとおりです。
docker pull <コンテナリポジトリ>:<コンテナタグ>
例えば、リポジトリから CentOS8 の Docker イメージを取得する場合は以下のコマンドとなります。
Docker イメージの一覧 images
Docker イメージの一覧を表示します。
REPOSITORY TAG IMAGE ID CREATED SIZE centos centos8 300e315adb2f 4 weeks ago 209MB
コンテナでコマンドを実行 run
docker run <コンテナリポジトリ>:<コンテナタグ> <実行するコマンド>
bin dev etc home lib (中略) var
ls コマンドが実行できたことがわかります。
コンテナの一覧 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ff53e74d2aec centos:centos8 "ls" 3 minutes ago Exited (0) 3 minutes ago upbeat_bardeen
ls コマンドの実行が完了し、終了(Exited)したコンテナを確認できます。
コンテナを削除 rm
終了している Docker コンテナを削除します。
コンテナ終了時に自動削除 --rm
終了したコンテナを毎回削除するのは手間なので、コンテナ起動時 (docker run) のオプションで、コンテナ終了時に自動削除するように設定します。
bin dev etc home lib (中略) var
停止したコンテナが削除されていることが確認できます。
コンテナの中に入る -it bash
bash コマンドの標準入力と標準出力をホスト側に変更することで、ホストから Docker コンテナに入ったかのように操作できます。
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
バックグラウンドで実行 -d
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 03e96e9e13a8 centos:centos8 "bash" 55 seconds ago Up 54 seconds nifty_kilby
コンテナの実行中のプロセスを表示 container top
UID PID PPID C STIME TTY TIME CMD root 5564 5521 0 12:18 pts/0 00:00:00 bash
実行中のコンテナで新しくコマンドを実行 exec
実行中のコンテナに対して、bash コマンドを実行してみます。
コンテナを終了する stop
コンテナに名前をつける --name
そろそろ毎回 CONTAINER ID を調べるのがめんどくさくなってきた頃でしょうか。
そんな時はコンテナに名前をつけましょう。
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES 0f1d8d7f52b9 centos:centos8 "bash" 3 seconds ago Up 2 seconds centos
NAMES が centos になっていることがわかります。
コンテナのポートをホスト側に公開 -p
「ホスト側の 8080 ポート」と「コンテナの 80 ポート」を紐付けます。
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title>
無事、ホスト側の 8080 ポートを利用して、nginx コンテナの 80 ポートにアクセスできました。
Docker イメージを削除 rmi
REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 12766a6745ee 5 days ago 142MB centos centos8 5d0da3dc9764 6 months ago 231MB
REPOSITORY TAG IMAGE ID CREATED SIZE centos centos8 5d0da3dc9764 6 months ago 231MB
コンテナにデータ・ボリュームを追加 -v
データ・ボリュームは主に以下の用途で利用します。
データ・ボリュームのマウントには以下の3つが存在します。
- 「volume」= 名前付きボリューム
- 「bind mount」 = ホスト側のパス
- 「tmpfs mount」 = メモリ (-v ではなく、--tmpfs を利用)
「名前付きボリューム」をデータ・ボリュームとしてマウント
名前付きボリュームは、オプション v の値をアルファベット文字「a-z0-9, "_", "." , "-"」で開始します。
名前
を指定する場合は、Docker は、その名前
を持つボリュームを作成します。https://docs.docker.jp/engine/reference/run.html#run-volume
名前
は英数字で始まる必要があり、以降はa-z0-9
、_
(アンダースコア)、.
(ピリオド)、-
(ハイフン)が使えます
以下に、名前付きボリューム「volume」をデータ・ボリュームとしてマウントする例を示します。
test.txt
test1 コンテナの /hoge が永続化されていたり、test2 コンテナで共有・再利用しています。
なお、名前付きボリュームは、Docker が管理するストレージエリアに保存されます。
(ホスト側の /var/lib/docker/volumes/)
test.txt
「ホスト側のパス」をデータ・ボリュームとしてバインドマウント
ホスト側のパスは、オプション v の値を「/」で開始します。
ホスト側ディレクトリ
に絶対パスを指定すると、 Docker は指定したパスをバインド・マウントします。絶対パスは
https://docs.docker.jp/engine/reference/run.html#run-volume/
(フォアワード・スラッシュ)で始める必要があります。
以下に、ホスト側のパス「/tmp」をデータ・ボリュームとしてマウントする例を示します。
host_side
ホスト側のボリューム /tmp/test.txt を、コンテナ側にデータ・ボリューム /hoge/test.txt としてバインドマウントできていることが確認できます。
ボリューム一覧を確認 volume ls
ホスト側で Docker が管理するストレージエリア /var/lib/docker/volumes/
に保存されたボリューム一覧を表示します。
DRIVER VOLUME NAME local volume
先ほど作成した volume という名前のボリュームが確認できます。
一括削除 system prune
以下のオブジェクトを一括削除します。
- 終了したコンテナ
- タグ無しイメージ (オプション -a で使われてないイメージも削除)
- 未使用ボリューム (オプション --volumes が必要)
- 未使用ネットワーク
Are you sure you want to continue? [y/N] y # y を押すと一括削除されます。
DRIVER VOLUME NAME
先ほど確認したボリュームは全て削除されていることが確認できます。
コンテナ、イメージ、ボリューム、ネットワークを別々に一括削除する場合は以下のとおりです。
終了したコンテナの一括削除
タグ無しイメージの一括削除
未使用ボリュームの一括削除
未使用ネットワークの一括削除
Dockerfile: Dockerイメージを作成
Dockerfile は ベースとなる Docker イメージから、新しい Docker イメージを作成する命令を記載したファイルです。
1回だけ環境構築する場合は docker exec *** でも良いですが、同じ環境を何度も構築する場合は Dockerfile に命令を書いてしまいましょう。2回目以降は Dockerfile を使いまわして環境構築できます。
Dockerfile で利用可能な命令一覧
Dockerfile で利用可能な命令の一覧は以下のとおりです。
命令 | 説明 |
---|---|
FROM | ベースイメージを設定 |
RUN | ベースイメージで実行するコマンドを指定(新しいDocker イメージの作成) |
CMD | コンテナの実行時のデフォルトで実行するコマンドを設定 |
LABEL | イメージにラベル(メタデータ)を追加 |
EXPOSE | コンテナ実行時にリッスンするポートを指定 |
ENV | 環境変数を設定 |
ADD | ローカルホストからイメージへファイルを追加 |
COPY | ローカルホストからイメージへファイルをコピー |
ENTRYPOINT | コンテナを実行モジュールとして実行するように設定 |
VOLUME | マウントポイントを生成 |
USER | RUN, CMD, ENTRYPOINT を実行するユーザーを指定 |
WORKDIR | ワークディレクトリを指定 |
ARG | ビルド時の引数を指定 |
ONBUILD | イメージに対してトリガーを追加 |
STOPSIGNAL | コンテナが終了する時に送信するシステムコールシグナルを追加 |
HEALTHCHECK | コンテナのヘルスチェック方法を指定 |
SHELL | デフォルトのシェルを指定 |
ADD と COPY の違い
基本的に COPY を使っておきましょう。COPY でやりたいことが出来ない場合は ADD の利用を検討します。
Although
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copyADD
andCOPY
are functionally similar, generally speaking,COPY
is preferred. That’s because it’s more transparent thanADD
.COPY
only supports the basic copying of local files into the container, whileADD
has some features (like local-only tar extraction and remote URL support) that are not immediately obvious. Consequently, the best use forADD
is local tar file auto-extraction into the image, as inADD rootfs.tar.xz /
.
CMD と ENTRYPOINT の違い
CMD | ENTRYPOINT | |
---|---|---|
目的 | コンテナ実行時のデフォルトのコマンドを指定 | コンテナ実行時のコマンドを固定 |
docker run <コマンド> | コマンドの上書き可能 | コマンドの上書き不可能 |
例: Dockerfile で nginx の Docker イメージを作成
Dockerfile を理解するために、CentOS8 の Docker イメージから以下のような nginx の Docker イメージを作成してみます。
Dockerfile を作成
Dockerfile から Docker イメージを作成
Nginx の Docker イメージから Docker コンテナを作成し、アクセス
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux</title>
無事に Dockerfile から Nginx をインストールした Docker イメージを作成可能なことを確認できました。
docker-compose: 複数のコンテナを実行
docker-compose は、複数のコンテナを一気に起動するためのファイルです。
docker-compose で利用可能な命令一覧は以下のとおりです。
docker-compose: インストール
Linux 系で docker-compose をインストール
docker-compose version 2.4.1, build 6d1ac21
Linux 系以外で docker-compose をインストール
以下のドキュメントに従ってインストールしてください。
docker-compose: 使い方
先程自作した Nginx と、公式の Nginx の2つの Docker イメージを利用して、2つのコンテナを起動する docker-compose を作成します。
docker-compose.yml ファイルの作成
version: '3' services: my_nginx: build: context: . dockerfile: Dockerfile ports: - "8080:80" official_nginx: image: nginx ports: - "8081:80"
Compose ファイル (docker-compose.yml) の書き方は以下のとおりです。
docker-compose で複数コンテナを一括起動
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a2acd90e276f nginx "nginx -g 'daemon of…" 6 minutes ago Up 6 minutes 0.0.0.0:8081->80/tcp http_official_nginx_1 f7cc5a4d0c56 http_my_nginx "/bin/sh -c '/usr/sb…" 6 minutes ago Up 6 minutes 0.0.0.0:8080->80/tcp http_my_nginx_1
自作した Nginx と、公式の Nginx の2つのコンテナが起動していることが確認できます。
また、それぞれのコンテナにアクセス可能なことも確認できます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux</title>
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title>
docker-compose でコンテナ群を一括終了
補足事項:名前付きボリューム
個人的にハマったのでメモ書きとして置いておきます。
名前付きボリュームを使うには、以下にあるようにトップレベルの
https://docs.docker.jp/compose/compose-file/compose-file-v3.html#volumesvolumes
キーに記述する必要があります。
つまり、以下のような記載をすると次のようなエラーが発生します。
version: "3" services: web: image: nginx:alpine volumes: - html:/usr/share/nginx/html/ ports: - "80:80"
ERROR: Named volume "html:/usr/share/nginx/html:rw" is used in service "web" but no declaration was found in the volumes section.
正しい記載は以下です。(docker run -v の名前付きボリュームの作成方法と異なります。)
version: "3" services: web: image: nginx:alpine volumes: - html:/usr/share/nginx/html/ ports: - "80:80" volumes: html:
関連記事
コンテナ環境構築シリーズの記事は以下のとおりです。
参考記事
公式ドキュメント
Docker 日本語ドキュメント(有志による翻訳)
Docker で検索すると一番上に出てくる Qiita の記事