dockerを触ってみる
centosのイメージを持ってくる
公式に解説があるので、それを参考にする。 https://hub.docker.com/_/centos/
途中で公式が解決方法を提供している問題をひとつずつ踏みながら、理解しつつ進むので少しまどろっこしい方法で理解する。
以下のようなDockerfileを作成する。
# cat Dockerfile FROM centos:7 MAINTAINER "you"ENV container docker RUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs RUN yum -y update; yum clean all; \ (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*;\ rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]
イメージをビルドする
Dockerfileからイメージをビルドする。
# docker build --rm -t local/c7-systemd .
作成されたことを確認する。
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE local/c7-systemd latest 55328d2ac5c8 6 minutes ago 229.4 MB
コンテナを起動する
次に、このイメージからコンテナを作成して、シェルを実行させる。 dockerにおけるコンテナは起動後に必ず一つのプロセスを動かす必要があるようだ。 シェルからapacheをインストールして、起動してみる。
# docker run -it local/c7-systemd /bin/bash [root@4747003b4111 /]# [root@4747003b4111 /]# yum install httpd [root@4747003b4111 /]# systemctl start httpd.service Failed to get D-Bus connection: No connection to service manager. [root@42ebe1f0dcb4 /]# ps auxww USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.2 0.1 11744 1872 ? Ss 05:09 0:00 /bin/bash root 18 0.0 0.1 19764 1228 ? R+ 05:09 0:00 ps auxww
コンテナのシェルのプロンプトが現れる。 「-it」はstdinを有効にするために必要らしい。 httpdをインストールして起動してみたが、エラーが出る。 psコマンドを見てもシェルから起動したプロセスしか現れない。これがコンテナか。
Dockerfileを以下のように書き換えて再実行。 apacheをインストールして、systemctlでhttpを起動してinitを実行する。
# cat Dockerfile FROM centos:7 MAINTAINER "you"ENV container docker RUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs RUN yum -y update; yum clean all; \ (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*;\ rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] FROM local/c7-systemd RUN yum -y install httpd; yum clean all; systemctl enable httpd.service EXPOSE 80 CMD ["/usr/sbin/init"]
先ほどと同様の方法で起動するが、失敗する。
# docker run -it local/c7-systemd Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning. systemd 208 running in system mode. (+PAM -LIBWRAP -AUDIT +SELINUX -IMA +SYSVINIT -LIBCRYPTSETUP -GCRYPT -ACL -XZ) Detected virtualization 'docker'. Welcome to CentOS Linux 7 (Core)! Initializing machine ID from container UUID. No control group support available, not creating root group. Please start this container with '-v /sys/fs/cgroup:/sys/fs/cgroup' Failed to allocate manager object: Operation not permitted
エラーが出て停止する。cgroupに関するエラーのようだ。
これは以下のようにコンテナを実行すると回避できる。
# docker run --privileged -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 local/c7-systemd
今度はエラーが出ない。起動時の表示が出たまま 以下のようにすると起動していることを確認できる。
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0c3958d6a846 local/c7-systemd:latest "/usr/sbin/init" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp adoring_almeida
変な名前「adoring_almeida」が付いている。なんだろこれ。
試しにホストのlocalhostの80版ポートにアクセスしてみる。
# telnet localhost 80 Trying ::1... Connected to localhost. Escape character is '^]'. GET / index.htmlが返ってくる。
GETできたので成功だ。
あとは終了して、コンテナを終了しておく。
# docker stop adoring_almeida adoring_almeida
他の方法
以下のようにすれば、もっと簡単に検証できらしい。 参照: CentOS 7のDockerコンテナ内でsystemdを使ってサービスを起動する
$ sudo docker run --privileged -d -p 80:80 --name httpd centos:centos7 /sbin/init $ sudo docker exec -it httpd /bin/bash # yum install httpd -y # systemctl enable httpd.service # systemctl start httpd.service # exit $ curl -s http://localhost/ | head -n 1
docker runとdocker execの違いを理解していないため、よくわからなくなってしまった。 以下がそれぞれのコマンドの役割である。
- docker run コンテナを起動する
- docker exec 実行中のコンテナで新しいコマンドを実行する
docker runで起動中のコンテナ上で新しいコマンドを起動したければdocker execを使う。
うえのほうで実行していたapacheのインストールと起動が失敗した理由は単純にDockerfileから起動したものに対してシェルを起動したつもりになっていて実はそうなっていなかったのかも。