CentOS7上のDockerでコンテナを固定IP化して幸せになりたい
背景
普段、開発環境としてWindows+VirtualBox+Vagrantを利用しているのですが、VMはリソースの消費が大きいことに日々悩んでいます。そこで、リソースが節約できそうなDockerでコンテナを固定IP化してVagrant的に利用できたら幸せになれる!という思惑から設定を考えてみました。(Docker的にはアンチパターンかもしれませんが。。。)
ゴール
- VirtualBoxのホストオンリーアダプタまたはブリッジアダプタのネットワーク上で指定した固定IPアドレスを持つコンテナを稼働させる。
私はWindows上のエディタ/IDEで開発するためにVMに固定IPを割り当ててSambaを稼働させてます。その兼ね合いでコンテナにも個別に固定IPアドレスを割り当てたいので上記のゴールを設定しています。
実は以前に似たような目的でpipeworkを使った下記の記事を投稿しましたが、pipeworkの手間が煩わしく使わなくなってしまいました。するとDockerが似たような機能を取り込んで手間が減ったので、今回あらためて記事にまとめてみました。
前提
- VirtualBox+Vagrant上に構築します。
- CentOS7のVagrantのBoxは作成済みとします。
※ CentOS公式のVagrantのBoxはファイルシステムがxfsではなくext4になっています。
※ 私はDockerのストレージエンジンにoverlayを使いたかったためxfsベースのBoxを自作しました。 - ホストオンリーアダプタのネットワークは192.168.77.0/24とします。
※ VirtualBoxのホストオンリーアダプタの設定と一致させます。 - ブリッジアダプタのネットワークは10.0.0.0/24とします。
※ ホストPCが参加しているネットワークと一致させます。
参考記事
下記の記事を参考にさせていただきました。
構築手順
1. VagrantでCentOS7のVMを起動
Vagrantfileを用意してvagrant upします。
ホストオンリーアダプタの場合は以下の内容でVagrantfileを用意します。Box名は適切なものに置換してください。
Vagrant.configure("2") do |config|
config.vm.box = "(Box名)"
config.vm.provider "virtualbox" do |v|
v.customize ['modifyvm', :id, '--nicpromisc2', 'allow-all']
end
config.vm.network "private_network", ip: "192.168.77.10", auto_config: false
end
ブリッジアダプタの場合は以下の内容でVagrantfileを用意します。
Vagrant.configure("2") do |config|
config.vm.box = "(Box名)"
config.vm.provider "virtualbox" do |v|
v.customize ['modifyvm', :id, '--nicpromisc2', 'allow-all']
end
config.vm.network "public_network", auto_config: false
end
Vagrantfileが用意できたらvagrant upします。
$ vagrant up
2. Dockerのインストール
VMが起動したらVMのCentOS7上でDockerの設定を行います。ここではrootで作業する前提で話を進めます。
(オプション)私はストレージエンジンにoverlayを使いたかったため、以下の設定を行ってvagrant reloadして再起動しています。
# tee /etc/modules-load.d/overlay.conf <<-'EOF'
overlay
EOF
Dockerのリポジトリを設定します。
# tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF
(オプション)ストレージエンジンにoverlayを使う場合は以下の追加設定を行います。
# mkdir -p /etc/systemd/system/docker.service.d
# tee /etc/systemd/system/docker.service.d/override.conf <<-'EOF'
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --storage-driver=overlay
EOF
Dockerをインストールして起動させます。
# yum -y install docker-engine
# systemctl enable docker.service
# systemctl start docker.service
Dockerが動作しているか確認します。
# docker info
(オプション)ストレージエンジンにoverlayを使う場合はdocker infoで設定されているか確認できます。
3. ブリッジの設定
CentOS7上にブリッジを作成していきます。
# yum -y install bridge-utils
# ip addr flush dev eth1
ホストオンリーアダプタの場合は以下のようにします。
# docker network create --driver bridge --subnet=192.168.77.0/24 --gateway=192.168.77.10 --opt "com.docker.network.bridge.name"="docker1" my_bridge
ブリッジアダプタの場合は以下のようにします。
# docker network create --driver bridge --subnet=10.0.0.0/24 --gateway=10.0.0.10 --opt "com.docker.network.bridge.name"="docker1" my_bridge
なお、「--gateway=」で設定するIPアドレスが作成されるブリッジのIPアドレスとして利用されますので、他で利用されていないIPアドレスを指定する必要があります。
その後、以下の設定を行います。
# mkdir -p /etc/systemd/system/docker.service.d
# tee /etc/systemd/system/docker.service.d/override2.conf <<-'EOF'
[Service]
ExecStartPost=/bin/sh -c "/usr/bin/sleep 1s; /usr/sbin/ip addr flush dev eth1; /usr/sbin/brctl addif docker1 eth1"
ExecStopPost=/bin/sh -c "/usr/sbin/brctl delif docker1 eth1"
EOF
# systemctl daemon-reload
設定が完了したらvagrant reloadして設定に問題ないか確認します。以下のようにdocker1にeth1が関連付けられていたらOKです。
# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02426630bacc no
docker1 8000.0242cdcc83a0 no eth1
コンテナイメージの作成
今回構築した環境用にCentOS6とCentOS7のイメージを作成します。
作成するイメージのゴール
- ログインID/パスワードがdocker/dockerのユーザを作成します。
- dockerユーザにsudo権限を与えます。
- sshdを稼働させます。(Docker的にはアンチパターンかもしれませんが。。。)
CentOS6のイメージ作成
以下の内容のDockerfileを作成します。
FROM centos:6.8
ENV container docker
RUN yum -y update && yum clean all
RUN yum -y install openssh-server openssh-clients passwd sudo && yum clean all && chkconfig sshd on
RUN groupadd docker && useradd -g docker docker && (echo "docker" | passwd docker --stdin) && sed -i 's/Defaults.*requiretty/#Defaults requiretty/g' /etc/sudoers && ssh-keygen -q -N "" -t dsa -f /etc/ssh/ssh_host_dsa_key && ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key && sed -ri 's/session required pam_loginuid.so/#session required pam_loginuid.so/g' /etc/pam.d/sshd && (echo "docker ALL=(ALL) NOPASSWD: ALL" >/etc/sudoers.d/docker)
CMD ["/sbin/init"]
ビルドします。
# docker build --rm -t local/c6 .
CentOS7のイメージ作成
FROM centos:7
ENV container docker
RUN (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/*;
RUN yum -y update && yum clean all
RUN yum -y install openssh-server openssh-clients passwd sudo && yum clean all && systemctl enable sshd.service
RUN groupadd docker && useradd -g docker docker && (echo "docker" | passwd docker --stdin) && sed -i '/^session.*pam_loginuid.so/s/^session/# session/' /etc/pam.d/sshd && sed -i 's/Defaults.*requiretty/#Defaults requiretty/g' /etc/sudoers && rm /usr/lib/tmpfiles.d/systemd-nologin.conf && /usr/bin/ssh-keygen -A -v && (echo "docker ALL=(ALL) NOPASSWD: ALL" >/etc/sudoers.d/docker)
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
ビルドします。
docker build --rm -t local/c7-systemd .
コンテナの起動
固定IPを指定して起動します。ここではホストオンリーアダプタのネットワーク上のIPアドレスの例になっていますが、ブリッジアダプタの場合は「--ip=192.168.77.11」の代わりに「--ip=10.0.0.11」などを指定することになります。指定した固定IPに対してsshなどが可能です。
CentOS6
# docker run --name container1 --network=my_bridge --ip=192.168.77.11 -d local/c6
CentOS7
# docker run --privileged --name container1 --network=my_bridge --ip=192.168.77.11 -v /sys/fs/cgroup:/sys/fs/cgroup:ro --stop-signal=$(kill -l RTMIN+3) -d local/c7-systemd
コンテナの停止と再稼働
通常通りのdocker stop/docker startで行います。
停止
# docker stop container1
再稼働
# docker start container1