こんにちは、鯨井貴博@opensourcetechです。
今回は、docker で Dockerfile を使用したコンテナの作成、
および起動を試してみます。
コンテナは、nginx on CentOS7 を作成しています。
docker環境は、Mac OS用のCommunity Edition(ver18.03.1-ce)を使っています。
Dockerfileの作成
以下のような Dockerfile を作りました。
MAINTAINER SubMattNesk(kujiraitakahiro) <*******@gmail.com>・・・②
COPY ./nginx.repo /etc/yum.repos.d/・・・③
RUN ["/bin/bash","-c","yum -y install nginx"]・・・④
EXPOSE 80・・・⑤
LABEL "version" = "0.02" \・・・⑥
"description" = "presented by SubMattNesk"
ADD ./emon.html /usr/share/nginx/html/・・・COPYと似てるけどちょっと違う
#ENTRYPOINT : When "docker run", you can't overwrite it.
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]・・・⑦
#CMD : When "docker run", you can overwrite it.
#For example, using command options.
CMD ["-c","/etc/nginx/nginx.conf"]・・・⑧
①FROM
FROM centos:latest
以下(Docker hub)にあるcentosのコンテナイメージの「latest」を元イメージとして使用しています。
https://hub.docker.com/_/centos/
②MAINTAINER
MAINTAINER SubMattNesk(kujiraitakahiro) <*******@gmail.com>
メンテナンスをしている人(管理者など)の情報を追記するもの。
③COPY
COPY ./nginx.repo /etc/yum.repos.d/
後のステップで実施する「docker build」時に、
操作PCのカレントディレクトリにある nginx.repoというファイルを
コンテナの /etc/yum.repos.d/ にコピーするもの。
④RUN
RUN ["/bin/bash","-c","yum -y install nginx"]
※上記のようにカッコ[ ]や、ダブルクォーテーション・カンマで書く方式を、EXEC方式という。
コンテナ構築時に実施するコマンドを指定するもの。
/bin/bash -c yum -y install nginxと書いても同じ意味(shell方式)。
⑤EXPOSE
EXPOSE 80
コンテナイメージで後悔するポートを指定するもの。
上記の場合、TCP80が公開される。
⑥LABEL
LABEL "version" = "0.02" \
"description" = "presented by SubMattNesk"
コンテナに付加するラベルを指定するもの。
複数指定したい場合は、上記のように「 \(バックスラッシュ)」 を使う。
⑦ENTRYPOINT
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
コンテナイメージ構築後に実施するコマンドを指定するもの。
※RUNと同様に、shell方式でもOK。
※Dockerfile内では一回しか使えず、複数行書いた場合には最後のものが実施される。
※systemctl(systemd)では起動出来ないので、注意。
⑧CMD
CMD ["-c","/etc/nginx/nginx.conf"]
ENTRYPOINTに続く、コマンドのオプションを指定しているもの。
※RUNと同様に、shell方式でもOK。
※ENTRYPOINTの中に含めてもいいが、
CMDで書くことで docker run時に上書き(例えば、/etc/nginx.confなど別の設定ファイルを指定するなど)が可能。
※Dockerfile内では一回しか使えず、複数行書いた場合には最後のものが実施される。
上記の他に、操作するユーザーを切り替える「USER」や、
カレントディレクトリを変更する「WORKDIR」・変数を定義する「ENV」などがあります。
詳細は、以下で確認してください。
ADD と COPY の違い
ADDの場合、リモートホストからのダウンロードや、圧縮されたファイルであれば解凍するなどの機能を持っていますが、
COPYは、操作PCにあるファイルを指定された先にコピーするだけ
コンテナイメージの作成
docker build コマンドを使います。
なお、前のステップで作成したDockerfile(その他、nginx.repoやemon.html)は、
作業時のカレントディレクトリに配置してあります。
※「---> Using cache」は、既にいくつかコンテナイメージがある場合のみ表示され(既存のイメージの再利用)、初めてコンテナイメージを作る時には表示されません。
Sending build context to Docker daemon 7.168kB
Step 1/9 : FROM centos:latest
---> 49f7960eb7e4
Step 2/9 : MAINTAINER SubMattNesk(kujiraitakahiro) <*******@gmail.com>
---> Using cache
---> 45d851346e99
Step 3/9 : COPY ./nginx.repo /etc/yum.repos.d/
---> Using cache
---> e4510b7db268
Step 4/9 : RUN ["/bin/bash","-c","yum -y install nginx"]
---> Using cache
---> 8705a0d8d7fd
Step 5/9 : EXPOSE 80
---> Using cache
---> 94cad7d5e020
Step 6/9 : LABEL "version" = "0.02" "description" = "presented by SubMattNesk"
---> Using cache
---> 56642d6c4f0c
Step 7/9 : ADD ./emon.html /usr/share/nginx/html/
---> Using cache
---> c3ef14035ef9
Step 8/9 : ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
---> Running in b5aec538ea91
Removing intermediate container b5aec538ea91
---> a280cbd2b5cc
Step 9/9 : CMD ["-c","/etc/nginx/nginx.conf"]
---> Running in 698c073be3b4
Removing intermediate container 698c073be3b4
---> 5c4776e2ffa1
Successfully built 5c4776e2ffa1
Successfully tagged sample/nginx2:latest・・・・作成されたコンテナイメージ
作成されたコンテナイメージには、「sample/nginx2」というタグが付けられています。
作成したコンテナイメージの確認
docker images コマンドを使います。
作成された「sample/nginx2」があることがわかります。
それ以外は、既にあったコンテナイメージです。
REPOSITORY TAG IMAGE ID CREATED SIZE
sample/nginx2 latest 5c4776e2ffa1 Less than a second ago 276MB
sample/nginx latest 2100cb31ecba 18 hours ago 276MB
centos latest 49f7960eb7e4 7 days ago 200MB
コンテナの起動
docker run コマンドを使います。
オプションは、以下のような意味があります。
-d:バックグラウンドで実施
-p:操作PCのTCP8080 と コンテナのTCP80 をバインド
-w:ワーキングディレクトリ指定
-t:タグ指定
また、起動確認は docker ps コマンドで行います。
dee3cdbdfe0b745fa770d71f10886a335ca9a29d4390e492d29970e358509174
bash-3.2$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dee3cdbdfe0b sample/nginx2 "/usr/sbin/nginx -g …" Less than a second ago Up 4 seconds 0.0.0.0:8080->80/tcp competent_proskuriakova
その他のオプションについては、以下を参照下さい。
docker run | Docker Documentation
docker run が失敗してコンテナがうまく起動出来なかった場合には、
以下のように docker ps で何も表示されず、docker ps -a とすると、
「Exited (0)」と書かれたものがあるので docker rm [CONTAINER ID]で残っているコンテナを削除してやり直します。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bash-3.2$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad12d45d2dd1 sample:0.02 "/bin/sh -c /usr/sbi…" 10 seconds ago Exited (0) 14 seconds ago blissful_ramanujan
以下、削除例です。
ad12d45d2dd1
bash-3.2$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bash-3.2$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
また、docker run がうまく出来ない場合、
前ステップの docker run で作られたコンテナイメージが良くないことがありますので、
docker rmi [コンテナイメージのタグ]として削除・Dockerfileの見直し・再docker buildしてやり直します。
REPOSITORY TAG IMAGE ID CREATED SIZE
sample 0.01 96c7fb19316c 2 hours ago 276MB・・・削除したいコンテナイメージ
kujiraitakahiro/submattnesk latest 96c7fb19316c 2 hours ago 276MB
bash-3.2$ docker rmi sample:0.01
Untagged: sample:0.01・・・削除された
bash-3.2$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kujiraitakahiro/submattnesk latest 96c7fb19316c 2 hours ago 276MB
dockerの情報確認
docker -v / docker version / docker info コマンドを使います。
bash-3.2$ docker -v
Docker version 18.03.1-ce, build 9ee9f40
bash-3.2$ docker version
Client:
Version: 18.03.1-ce
API version: 1.37
Go version: go1.9.5
Git commit: 9ee9f40
Built: Thu Apr 26 07:13:02 2018
OS/Arch: darwin/amd64
Experimental: false
Orchestrator: swarm
Server:
Engine:
Version: 18.03.1-ce
API version: 1.37 (minimum version 1.12)
Go version: go1.9.5
Git commit: 9ee9f40
Built: Thu Apr 26 07:22:38 2018
OS/Arch: linux/amd64
Experimental: true
bash-3.2$ docker info
Containers: 1
Running: 1
Paused: 0
Stopped: 0
Images: 10
Server Version: 18.03.1-ce
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 773c489c9c1b21a6d78b5c538cd395416ec50f88
runc version: 4fc53a81fb7c994640722ac585fa9ca548971871
init version: 949e6fa
Security Options:
seccomp
Profile: default
Kernel Version: 4.9.87-linuxkit-aufs
Operating System: Docker for Mac
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 1.952GiB
Name: linuxkit-025000000001
ID: MKEX:SNWC:G2C4:EW4Z:5ZPR:OFYF:EILE:C35S:SODF:CHWN:KFFZ:GHJW
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): true
File Descriptors: 30
Goroutines: 53
System Time: 2018-06-12T12:51:01.248400321Z
EventsListeners: 2
HTTP Proxy: docker.for.mac.http.internal:3128
HTTPS Proxy: docker.for.mac.http.internal:3129
Registry: https://index.docker.io/v1/
Labels:
Experimental: true
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
作成したコンテナへのアクセス
今回は nginx(Webサーバ)を構築したので、
操作PCのブラウザから 「http://localhost:8080」や「http://localhost:8080/emon.html」とすれば、
以下のようにコンテンツファイル(index.htmlやemon.html)が開きます。
コンテナ内でのコマンド操作
コンテナ内でも、通常のLinuxと同様のコマンドラインを使用することが可能です。
方法は3つ。
1つ目は docker exec コマンドを使用し、指定したコマンドのみ実施する方法。
bash-3.2$ docker exec 93d11e92e83d ping 1.1.1.1 -c 3
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=37 time=17.1 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=37 time=22.5 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=37 time=16.8 ms
--- 1.1.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2007ms
rtt min/avg/max/mdev = 16.868/18.877/22.599/2.634 ms
bash-3.2$ docker exec 93d11e92e83d echo "Hello, World"
Hello, World
2つ目は、docker exec コマンドで /bin/bash(シェル)を実施し、継続的に操作する方法。
コンテナから抜けるときは、exit とします。
[root@93d11e92e83d ~]# cat /etc/redhat-release ・・・・コンテナのシェル
CentOS Linux release 7.5.1804 (Core)
[root@93d11e92e83d ~]# exit
exit
bash-3.2$
3つ目は、docker attach で接続する方法。
attachからの抜け出し方は、ctrl(押したまま)p、qとタイプ。
もしくは、exitコマンドをコンテナ内で実施する(コンテナプロセスが停止するので注意)。
コンテナのプロセス確認
docker top コマンドを使います。
PID USER TIME COMMAND
2355 root 0:00 nginx: master process /usr/sbin/nginx -g daemon off; -c /etc/nginx/nginx.conf
2386 999 0:00 nginx: worker process
コンテナの停止
docker stop コマンドを使います。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dee3cdbdfe0b sample/nginx2 "/usr/sbin/nginx -g …" Less than a second ago Up 4 seconds 0.0.0.0:8080->80/tcp competent_proskuriakova
bash-3.2$ docker stop dee3cdbdfe0b
dee3cdbdfe0b
bash-3.2$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
※起動中のコンテナの元になったコンテナイメージ(docker imagesで表示)を削除するには、コンテナの停止(docker stop)・コンテナの削除(docker rm)が必要ですのでご注意。
おまけ:コンテナ起動につけられる名前について
以下の起動しているコンテナを見ると、NAMESの項目が「competent_proskuriakova」となっているのが分かります。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dee3cdbdfe0b sample/nginx2 "/usr/sbin/nginx -g …" Less than a second ago Up 4 seconds 0.0.0.0:8080->80/tcp competent_proskuriakova
複数コンテナを起動してみるとわかるのですが、
他にも「relaxed_liskov」や「festive_wescoff」など、
誰やねん!と突っ込みたくなるような名前がつけられています。
これは、名無し状態のコンテナに自動的に名前が付けられるもので、
GO言語で書かれた docker のソースコードを辿っていけば分かるのですが、
names-generator.go によって生成されている名前となります。
moby/names-generator.go at master · moby/moby · GitHub
docker のソースコードのトップは、以下。
なお、docker run 実行時に「--name」オプションを使えば任意の名前を付ける事で回避出来ます。
93d11e92e83d2a5786ccbabee0a4a6dc6138a47a87060c146d23cf512bf44d4b
bash-3.2$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
93d11e92e83d sample/nginx2 "/usr/sbin/nginx -g …" 3 seconds ago Up 1 second 0.0.0.0:8080->80/tcp test1