Dockerクイックスタートガイド
Dockerの作業フロー
コンテナ起動までの流れは、おおよそ次の通りである。
- コードを書く。
- Dockerイメージをビルドする。
- リポジトリへイメージをプッシュする。
- 本番環境でイメージをダウンロードする。
- コンテナを起動する。
docker pull: Dockerイメージを取得する
まず、2番まで作成済みのものを利用する方法として、docker pull コマンドについて見ていく。
Docker Hubにアップロードされたイメージをダウンロードすればよい。Docker Hub以外に、別途構築したDocker Registryからもダウンロードできる。
イメージをダウンロードするためのコマンドは次の形式である。
docker pull [イメージ名](:バージョン)
例えば、nginxをpullすると次のようになる。
$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
5b1423465504: Pull complete
1cdde8b981f2: Pull complete
6c0b05f215c0: Pull complete
004f1937a10a: Pull complete
fd61d71c75fe: Pull complete
717bf61a04cf: Pull complete
Digest: sha256:b95a99feebf7797479e0c5eb5ec0bdfa5d9f504bc94da550c2f58e839ea6914f
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
また、イメージ名の後にタグを付けてVersionを指定することもできる。何も指定しなければ最新バージョン(latest)が指定される。
nginxにバージョンを指定する方法は次の通りである。
$ docker pull nginx:1.21.1
docker images: Dockerイメージ一覧を確認する
ダウンロードした、または作成したイメージの一覧は次のコマンドで確認できる。
docker images
例えば、コマンドの実行結果は次のように表示される。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest fc5ec3f147e4 13 days ago 135MB
docker rmi: Dockerイメージを削除する
不要になったイメージは次のコマンドで削除できる。
docker rmi [イメージID|イメージ名]
例えば、nginxを rmi で削除すると次のようになる。
$ docker rmi nginx
Untagged: nginx:latest
Untagged: nginx@sha256:b95a99feebf7797479e0c5eb5ec0bdfa5d9f504bc94da550c2f58e839ea6914f
Deleted: sha256:fc5ec3f147e43825672b6b308944040fa0ba4a547f4b50e911770f0d154eeed0
Deleted: sha256:3e85098616c4513b241d95d1a0c49740da10d191738bdd6b9220eab71ad15ddb
Deleted: sha256:714a2b51cf12dfc0219555fc2c71ff56a99da0f257fc1e81fbdc722d55821519
Deleted: sha256:ca9b331c8e9078528f222eacfdff111fc19a511e3f6282d307780b2d06da0e2a
Deleted: sha256:082aa9054c2265e06a3a62ab2afdbeb22768565808c7e5143f4652a997825b06
Deleted: sha256:f5355920965616631532773783ab892ba7d5b686833964b34968bd64d22b5521
Deleted: sha256:21ec097e7be7f53b7882fa719131a83be79e5b65e73993fa54929e5065e5b3e5
削除した後、実際に削除されたか確認してみよう。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
上の rmi コマンドでnginxが削除されたことを確認できる。
docker run: Dockerを実行する
Docker Imageからコンテナを起動するには、次のコマンドを実行する。
docker run [イメージ名] (オプション)
オプションを付けなくても起動できるが、より便利に使用するために次のようなオプションが用意されている。
ここではよく使用するオプションのみを記載しているため、その他のオプションについては Docker公式 ドキュメントを参照してほしい。
| オプション | 意味 | 使用例 |
|---|---|---|
--name |
コンテナ名を指定 | docker run --name "test" nginx |
-d |
バックグラウンド実行 | docker run -d nginx |
-it (shell指定) |
コンソールに結果を出力 | docker run -it nginx bash |
-p host:container |
ポートマッピング | docker run -p 8080:80 nginx |
-v host:container |
ディレクトリ共有 | docker run -v /test1:/test2 nginx |
-e |
環境変数設定 | docker run -e foo=bar nginx |
-w |
内部の作業ディレクトリを指定 | docker run -it -w=/tmp/work nginx bash |
例として、起動時の設定と実行コマンドは次の通りである。
docker run --name my-nginx -p 8080:80 -v ~/develop/docker:/usr/share/nginx/html -e foo=bar -w /tmp/work -it nginx bash
- 使用するイメージ: nginx
- コンテナ名: my-bash
- ポート: コンテナの80ポートをホストの8080にマッピング
- ディレクトリ: ホストの
~/develop/dockerをコンテナの/usr/share/nginx/htmlにマウント - 環境変数:
fooにbarを設定 - 作業ディレクトリ:
/tmp/work - コンソールに結果を出力
- シェルはbashを指定
docker ps: コンテナ一覧を確認する
コンテナ一覧を確認するコマンドは次の通りである。この場合、稼働中のコンテナのみが表示される。
docker ps
実行中のコンテナを確認してみよう。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
caf5180d8506 nginx "/docker-entrypoint...." 4 minutes ago Up 7 seconds 0.0.0.0:8080->80/tcp my-nginx
実行中のコンテナがなければ、次のように表示される。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
停止したコンテナを含めてすべてのコンテナを見たい場合は、-a オプションを追加して実行すればよい。
docker ps -a
-a オプションを追加して実行すると、次のように停止したコンテナも確認できる。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
caf5180d8506 nginx "/docker-entrypoint...." 6 minutes ago Exited (0) 32 seconds ago my-nginx
Docker実行停止: docker stop
実行中のコンテナを停止するには、次のコマンドを実行する。
docker stop [コンテナID|コンテナ名]
ここで出てくる「コンテナID」と「コンテナ名」は、上で docker ps を実行したときに出力される左端と右端の列 CONTAINER ID、NAME である。
実習として、まずnginxを実行する。
$ docker run --name my-nginx -p 8080:80 -v ~/develop/docker:/usr/share/nginx/html -d nginx
caf5180d85067eae71a9ee6f4bb52e8222cc7f6a54b4b318384d0cd2c8794a63
起動したら、コンテナを停止する。
$ docker stop my-nginx
my-nginx
docker logs: コンテナ実行ログを確認する
コンテナ実行ログを見る方法は次の通りである。
docker logs [コンテナID|コンテナ名]
上で docker ps を実行して表示されたコンテナを基準にすると、次のようにコマンドを入力すればよい。
$ docker logs caf5180d8506
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
... 中略 ...
2022/09/05 18:20:28 [notice] 1#1: start worker process 27
2022/09/05 18:20:28 [notice] 1#1: start worker process 28
docker inspect: コンテナのメタデータを確認する
コンテナのメタデータを見るには、次のコマンドを使用する。
docker inspect [コンテナID|コンテナ名]
実際にコマンドを実行すると、次のように出力される。
% docker inspect caf5180d8506
[
{
"Id": "caf5180d85067eae71a9ee6f4bb52e8222cc7f6a54b4b318384d0cd2c8794a63",
"Created": "2022-09-05T18:10:41.606382836Z",
"Path": "/docker-entrypoint.sh",
"Args": [
"nginx",
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 5950,
"ExitCode": 0,
... 中略 ...
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
docker exec: Docker内で実行する
バックグラウンドで実行している現在動作中のコンテナに入るには、次のコマンドを使用する。このとき、シェルを指定する必要がある。
docker exec -it [コンテナID|コンテナ名] [Shell名]
my-nginx コンテナにbashを指定して入る。
$ docker exec -it my-nginx bash
root@61dc29dec3e4:/tmp/work#
docker rm: コンテナを削除する
停止したコンテナは次のコマンドで削除できる。
docker rm [コンテナID|コンテナ名]
上で使用したコンテナ my-nginx を削除してみる。
$ docker rm my-nginx
my-nginx
コンテナ、イメージの一括削除
上で、docker rmi、docker rm コマンドにより、それぞれイメージ削除、コンテナ削除ができることを説明した。このコマンドではそれぞれ削除対象を指定する必要があるため、一括で削除したい場合には不便である。一括削除の方法は次の通りである。
停止したコンテナと匿名イメージの削除:
docker system prune
起動中のコンテナを含めてすべてのコンテナを削除:
docker rm -vf $(docker ps -a -q)
すべてのイメージを削除:
docker rmi -f $(docker images -a -q)
Docker Imageを作る
上ではDocker Imageを取得する方法として、Docker Hubからリポジトリをpullした。
このほかにもDocker Imageを取得する方法はいくつかあり、ここでは次の2点を見ていく。
- コンテナからイメージを作る。
- Dockerfileに記述する。
コンテナからイメージを作る
コンテナ内で新しくパッケージをダウンロードした場合、起動時に使用したイメージから作成されるコンテナとは異なる状態のコンテナになる。このように新しく追加が行われたコンテナを作成できるイメージを作る方法として、次のコマンドがある。
docker commit [コンテナID] [新しく作成されるコンテナ名]
docker container ls
docker container ls コマンドを実行したときに表示される項目について見ていこう。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2axaf8tx4gjd registry "/entrypoint.sh /etc..." 7 weeks ago Up 7 weeks 0.0.0.0:5000->5000/tcp devkuma-private-registry
実行中のコンテナおよび終了したコンテナを表示するコマンドである。
| 項目 | 内容 |
|---|---|
| CONTAINER ID | コンテナを識別するための一意な識別子 |
| IMAGE | コンテナを作成するために使用したDocker Image |
| COMMAND | コンテナで実行されるアプリケーションプロセス |
| CREATED | コンテナ作成後の経過時間 |
| STATUS Up | Up(実行中)、Exited(終了)などのコンテナ実行状態 |
| PORTS | ホストポートとコンテナポートの接続関係(ポートフォワーディング) |
| NAMES | コンテナ名 |
Dockerfileに記述する
Dockerfileにイメージに関する設定を書くと、イメージを作成できる。Dockerイメージを作成するときに必ず必要な設定ファイルである。 このファイルに書かれた命令、つまりinstructionによってイメージが作成される。
Dockerfileは次の通りである。
Dockerfile
FROM centos:7
RUN echo "now building..."
RUN yum -y install httpd
RUN sed -i '/#ServerName/a ServerName www.example.com:80' /etc/httpd/conf/httpd.conf
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
このファイルを見ると、FROM や RUN、ADD などの命令と引数という構造でDockerfileが書かれていることがわかる。FROM、RUN、ADD などの命令がそれぞれ何を意味し、どのように使うかは次の表の通りである。ここでもよく利用するものだけを挙げているため、それ以外については公式ドキュメントを参照してほしい。
| 命令 | 意味 | 使い方 |
|---|---|---|
| FROM | ベースイメージを指定 | FROM [イメージ名] または FROM [イメージ名]:[タグ] |
| RUN | コマンド実行 | RUN [コマンド] |
| CMD | コンテナ起動時の実行コマンド | CMD [コマンド] または CMD ["実行バイナリ", "パラメータ1", "パラメータ2"] |
| EXPOSE | ポート公開 | EXPOSE [ポート] |
| VOLUME | マウント | VOLUME ["/data"] |
| ADD | ファイル/ディレクトリ追加 | ADD [ソース] [対象] |
| COPY | ファイル/ディレクトリコピー | COPY [ソース] [対象] |
| WORKDIR | 作業ディレクトリ指定 | WORKDIR [ディレクトリパス] |
| ENV | 環境変数設定 | ENV [key]=[value] |
インストラクション(instruction)
FROM
- 対象Dockerイメージのベースイメージを指定する。
mysqlを指定する場合は次の通りである。
FROM mysql
COPY
- ホストコンピュータのファイルやディレクトリをDockerコンテナにコピーする。
- イメージがBuildされるときに一度だけ実行される。
COPY ./cnf/my.cnf /etc/mysql/conf.d/my.cnf
RUN
- DockerイメージをDockerで実行するコマンドを定義する。
- COPYと同様に、Buildされるときに一度だけ実行される。
- 特別な指示がない場合は使用されない。
次は Test.java を javac でコンパイルしている。
RUN javac Test.java
ADD
基本はCOPYと同じで、次のような機能が追加されている。
- sourceがremote URLの場合、ダウンロード後にdestinationへコピーする。
- sourceがよく使われる圧縮ファイル形式(zipなど)の場合、展開する。
- sourceがremote URL + 圧縮ファイル形式の場合、展開しない。
CMD
- コンテナで実行するプロセス(コマンド)を指定する。これはイメージを実行するたびに実行されるコマンドである。
- CMDはDockerfileに1つだけ作成できる。複数作成した場合、最後の命令だけが実行される。
次は mysqld を実行している。
CMD ["mysqld"]
Dockerビルド: docker build
上のDockerfileの命令を見ると、docker run のオプションに似たことができる。
このように作成したDockerfileを使用してImageをビルドするには、次のコマンドを使用する。
docker build [Dockerfileパス]
基本的には Dockerfile という名前を使用する。ファイル名を変更する場合は、Build時に追加オプション -f を指定する必要がある。
このビルドを実行したときのイメージは、Dockerfileの各行(Layer)ごとに1つずつ実行していくように作成される。
これはビルド実行時の出力を見るとわかる。上のDockerfileを実行すると次のようになる。
$ docker build .
[+] Building 89.3s (8/8) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 252B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 5.0s
=> [1/4] FROM docker.io/library/centos:7@sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407 49.1s
=> => resolve docker.io/library/centos:7@sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407 0.0s
=> => sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407 1.20kB / 1.20kB 0.0s
=> => sha256:73f11afcbb50d8bc70eab9f0850b3fa30e61a419bc48cf426e63527d14a8373b 530B / 530B 0.0s
=> => sha256:c9a1fdca3387618f8634949de4533419327736e2f5c618e3bfebe877aa331352 2.77kB / 2.77kB 0.0s
=> => sha256:6717b8ec66cd6add0272c6391165585613c31314a43ff77d9751b53010e531ec 108.37MB / 108.37MB 46.2s
=> => extracting sha256:6717b8ec66cd6add0272c6391165585613c31314a43ff77d9751b53010e531ec 2.6s
=> [2/4] RUN echo "now building..." 0.3s
=> [3/4] RUN yum -y install httpd 34.3s
=> [4/4] RUN sed -i '/#ServerName/a ServerName www.example.com:80' /etc/httpd/conf/httpd.conf 0.2s
=> exporting to image 0.2s
=> => exporting layers 0.2s
=> => writing image sha256:b32d2ca733218ab8a1d1840b775d2baed16cab3e1775477ae3839e990ffbc479 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
この出力結果を見ると、Dockerfileに書いた通り、FROM で指定したベースイメージの上に、各行(Layer)が1つずつ実行されていくことがわかる。
新しいイメージが作成されたか確認できる。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> b32d2ca73321 13 minutes ago 417MB
ここでは REPOSITORY、TAG が <none> で、指定されていないことがわかる。
また、次のコマンドで上の内容を再確認することもできる。
docker history [イメージID|イメージ名]
$ docker history b32d2ca73321
IMAGE CREATED CREATED BY SIZE COMMENT
b32d2ca73321 9 minutes ago CMD ["/usr/sbin/httpd" "-D" "FOREGROUND"] 0B buildkit.dockerfile.v0
<missing> 9 minutes ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 9 minutes ago RUN /bin/sh -c sed -i '/#ServerName/a Server... 11.8kB buildkit.dockerfile.v0
<missing> 9 minutes ago RUN /bin/sh -c yum -y install httpd # buildk... 117MB buildkit.dockerfile.v0
<missing> 9 minutes ago RUN /bin/sh -c echo "now building..." # buil... 0B buildkit.dockerfile.v0
<missing> 6 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 6 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc... 0B
<missing> 6 months ago /bin/sh -c #(nop) ADD file:5b1e63a3cb041177b... 301MB
作成したイメージをpushする
上のような方法で作成したイメージをDocker Hubに公開する方法を見ていく。
まずDocker Hubのアカウントが必要なので、次のサイトで作成する。
公開するには、まずタグを指定する必要がある。次のようにDocker Hubで登録したユーザー名を使ってタグを付ける。
docker tag [Image ID] [DockerHubユーザー名]/[リポジトリ名]
上で新しく作成したイメージにタグを指定するには、次のコマンドを実行すればよい。
docker tag b32d2ca73321 devkuma/centos7
実行しても何も表示されない。
% docker tag b32d2ca73321 devkuma/centos7
イメージを確認すると、REPOSITORY、TAG が指定した通りに入っていることがわかる。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
devkuma/centos7 latest b32d2ca73321 17 minutes ago 417MB
そしてpushする前にDocker Hubへログインする必要があるため、次を実行してログインする。
docker login
% docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: devkuma
Password:
Login Succeeded
Logging in with your password grants your terminal complete access to your account.
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/
user@AL02263852 docker
ここまで完了すれば、Docker Hubにリポジトリをアップロードできるようになった。
docker push [DockerHubユーザー名]/[リポジトリ名]
次のコマンドを実行する。
$ docker push devkuma/centos7
Using default tag: latest
The push refers to repository [docker.io/devkuma/centos7]
5818d7ffd9ac: Pushed
085e94a3a50e: Pushed
6a9a145374b8: Pushed
65f23ff12f4d: Mounted from library/centos
latest: digest: sha256:2845b5f6439dff6a80ed8ed45a10cfd39e19d8178182fe043db939ccc3b7f982 size: 1156
複数コンテナ管理(docker-compose)
複数のコンテナを起動・停止したい場合、それぞれに対して docker run、docker stop を実行するのは時間がかかる。これを解決するために一括管理するものがdocker-composeである。この方法では、yamlファイル(docker-compose.yaml)に複数コンテナの情報を書いて管理する。
サンプルファイルの内容は次の通りである。
docker-compose.yaml
version: '3'
services:
db:
image: postgres
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
詳しい内容はここでは説明しないが、おおまかには version 属性にdocker-composeのversionを入れ、services 属性には起動したいサーバーの情報を入れる。このファイルの場合、DBサーバーとWebサーバーをそれぞれ起動するように書かれている。また、その下に書かれている内容はDockerfileに書く内容と似ている。詳しい内容は Docker公式ドキュメント を参照してほしい。
このようなyamlファイルを作成した後、次のコマンドを実行してコンテナを起動できる。
docker-compose –f [yamlファイルパス] up
起動したコンテナについて、yamlファイルに列挙されたコンテナを停止するには次のコマンドを実行する。
docker-compose -f [yamlファイルパス] dowm
このように起動した複数コンテナのログをまとめて見たい場合は、次のコマンドを実行する。
dokcer-compose -f [yamlファイルパス] logs
サーバーのクラスタ化構成などを行うため、Webサーバーなどを複数台起動したい場合がある。このように複数台起動して同じ役割を果たすものを、コンテナの複製(replica)という。このdocker-composeでコンテナの複製を複数起動する方法を見てみよう。
複数起動を行うには、上のyamlファイルのポート設定を変更する必要がある。特に、各コンテナでポートが重複しないように範囲表記する必要がある。
docker-compose2.yaml
version: '3'
services:
db:
image: postgres
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000-3004:3000"
depends_on:
- db
このように内容を変更すると、ホスト側ポートに3000、3001、3002、3003、3004が割り当てられるため、5つの複製セットを作成できる。このdocker-composeファイルを使用して起動するが、up コマンドを実行するときに --scale オプションを追加し、複製数を指定する。
docker-compose –f [yamlファイルパス] up –scale [コンテナ名]=[複製数]
ネットワーク
docker-composeで定義されたコンテナは、デフォルト設定で相互に通信できる。しかし、別の場所、つまりyamlに書かれたコンテナ以外のコンテナからはアクセスできないようになっている。これは、コンテナ起動時にネットワーク名前空間が作られ、コンテナに割り当てられるためである。
コンテナを個別に起動した場合、特に設定しなければ、デフォルトで用意されているBridgeネットワークに接続されるようにネットワーク名前空間が作られる。一方、docker-composeで作成したコンテナ群は、別のBridgeネットワークを個別に設定し、そのBridgeネットワークに接続されるようにネットワーク名前空間が作られる。
したがって、docker-composeで作成したコンテナと個別に作成したコンテナは通信できない。
この問題を解決して接続するには、ネットワークを設定する必要がある。ここでは説明しないが、後ほどこの内容について扱う。
ネットワーク一覧を見るには、次のコマンドを実行する。
docker network ls
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
7f8103f64ff5 bridge bridge local
540c2f32637b host host local
a0053c593c0e none null local
この出力結果を見ると、DRIVER列にいくつかの種類があることがわかる。これはネットワークモードに該当する。Dockerネットワークには次の4つのモードがある。
- bridge
- ホスト内のDockerBridgeネットワークからIPが割り当てられるため、IPレンジはホストとは別になる。
- host
- ホストのIPレンジからIPが分けられ、さらにホストのポートを利用するため、
-pオプションなどによるポートマッピングはできない。
- ホストのIPレンジからIPが分けられ、さらにホストのポートを利用するため、
- null
- Bridgeにもホストにもリンクされず、IPが割り当てられない。したがって接続不可状態になる。
- overlay
- 複数ホストの場合に使用する。
新しいネットワークを作成するには、次のコマンドを実行する。
docker network create –driver bridge [ネットワーク名]
ネットワークを削除するには、次のコマンドを実行する。
docker network rm [ネットワーク名]
ストレージ
コンテナはライフサイクルが短い場合があり、データはコンテナではなくホストに保存される。
そのため、docker run コマンドで -v により指定したように、ホストのフォルダとコンテナのフォルダを指定してマウントを行う。