2020年6月9日火曜日

Docker入門 (Dockerfileを作ってコンテナを作成する)

前回はDocker入門として、Dockerのインストールと各種コマンドを使ってCentOS 7のコンテナを作成し、Squidを動作させる手順を記事にした。

★前回の記事はこちら↓
Docker入門 (CentOS 7にDocker CEインストール&CentOSコンテナを作成してSquidを動かす)

上記において、CentOSのコンテナ作成後に、yumによるパッケージインストールや設定ファイルの修正などの各種処理を実施している。Dockerではこれらの手作業で実施していた処理を自動化することができ、「Dockerfile」と呼ばれる定義ファイルにあらかじめ処理を記載しておくことで実現する。

今回は前回手作業で作成したCentOS 7 + SquidのコンテナをDockerfileを使って自動作成する手順について記載する。

環境

  • OS : CentOS 7.8
  • Docker : 19.03.10
  • コンテナ上のCnetOS : 7.6 (あえてホストとは別バージョンにしてみた)

Dockerfile作成

Dockerfileでは、「命令」として定義された文字列の後に、実際にコンテナで実行したいコマンドなどを記述することで作成される。主な「命令」は以下の通りとなる。

命令 説明
FROM ベースとするイメージを指定する。今回はCentOS 7を使用するが、Docker推奨はDebianのイメージを使うことらしい。
ENV 環境変数を設定。
RUN イメージ作成のためのコマンドを記載する。
CMD 作成したイメージからコンテナを作成する際に実行するデフォルトのコマンドを記載する。Dockerfile内に1個だけ記載することができる。RUNと似ているが、RUNはイメージ作成時に実行するコマンドに対し、CMDはコンテナ作成時に実行するデフォルトのコマンドとなる。したがって、CMDで定義したコマンドはイメージ作成時には実行されることはない
EXPOSE コンテナが使用する(LISTENする)ポートを指定する。実際は記載しなくてもdocker run実行時に-pでポートを指定すればコンテナの任意のポートをホストに公開できるため、あくまでも人間がDockerfileを見た際に、コンテナが使用するポートを理解するための命令として用意しているようだ。

Dockerfileにて必要な命令を記述し、上から順に実行していくことでコンテナのイメージを作成していくことができる。この際に、可能な限り命令は少なくなるよう構成することが望ましい。というのもDockerでは、Dockefileの各命令が実行される際に再利用を目的として、「レイヤ」と呼ばれる命令実行時点のイメージの静止点を保持するのだが、このレイヤが多くなればなるほど、処理に時間を要するためである。

例として、実際のDockerfileで見てみよう。以下は私が最初に作成したCentOS 7でSquidを動作させるイメージを作成するためのDockerfileとなる。FROMENVRUNEXPOSEの命令が合計8個定義されていることがわかる。

FROM centos:7.6.1810

ENV http_proxy http://192.168.33.23:8080
ENV https_proxy http://192.168.33.23:8080
RUN yum install squid -y
RUN yum clean all
RUN systemctl enable squid
RUN echo $'\n\
acl localnet src 192.168.33.0/24\n\
acl localnet src 192.168.11.0/24\n\
cache_peer 192.168.33.23 parent 8080 7 no-query no-netdb-exchange\n\
never_direct allow all\n\
' >> /etc/squid/squid.conf

EXPOSE 3128

最終的に整理したDockerfileは以下の通り。命令は6つに集約されていることがわかる。また、以下もあわせて改善した。

  • squid.confへの追記において、一部設定ファイルの途中に追記が必要な設定があるためsedによる追記に修正
  • echoを視認性の高い記載に変更
  • docker runコマンド時に--privilegedオプション使わないようにするため、CMD命令にてSquidを実行する形式に変更
FROM centos:7.6.1810

ENV http_proxy=http://192.168.33.23:8080 https_proxy=http://192.168.33.23:8080
RUN yum install squid -y && yum clean all
RUN sed -ie "/^acl SSL_ports port 443$/i acl localnet src 192.168.33.0/24\nacl localnet src 192.168.11.0/24\n" /etc/squid/squid.conf && \
    { \
      echo ; \
      echo "cache_peer 192.168.33.23 parent 8080 7 no-query no-netdb-exchange"; \
      echo "never_direct allow all"; \
    } >> /etc/squid/squid.conf

EXPOSE 3128
CMD /usr/sbin/squid -N -f /etc/squid/squid.conf

イメージをビルド

イメージのビルドはdocker buildコマンドで行う。指定したディレクトリにあるファイルをすべて読み取ってしまうことから、ビルドは必ずDockerfileだけが置いてあるディレクトリを作成したうえで実行すること。ビルドを実行すると、定義した命令単位でStepとして実行していくことがわかる。

# cd docker-squid/
# docker build -t docker-squid:1 .
Sending build context to Docker daemon   2.56kB
Step 1/6 : FROM centos:7.6.1810
 ---> f1cb7c7d58b7
Step 2/6 : ENV http_proxy=http://192.168.33.23:8080 https_proxy=http://192.168.33.23:8080
 ---> Running in 286323b4dd03
Removing intermediate container 286323b4dd03
 ---> e7e0e325cbc6
Step 3/6 : RUN yum install squid -y && yum clean all
 ---> Running in e647c5926282
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * updates: ftp-srv2.kddilabs.jp
Resolving Dependencies
--> Running transaction check
---> Package squid.x86_64 7:3.5.20-15.el7_8.1 will be installed
--> Processing Dependency: squid-migration-script for package: 7:squid-3.5.20-15.el7_8.1.x86_64
--> Processing Dependency: perl(warnings) for package: 7:squid-3.5.20-15.el7_8.1.x86_64

~(中略)~

  perl-threads.x86_64 0:1.87-4.el7
  perl-threads-shared.x86_64 0:1.43-6.el7
  squid-migration-script.x86_64 7:3.5.20-15.el7_8.1

Complete!
Loaded plugins: fastestmirror, ovl
Cleaning repos: base extras updates
Cleaning up list of fastest mirrors
Removing intermediate container e647c5926282
 ---> bfded9857d0d
Step 4/6 : RUN sed -ie "/^acl SSL_ports port 443$/i acl localnet src 192.168.33.0/24\nacl localnet src 192.168.11.0/24\n" /etc/squid/squid.conf &&     {       echo ;       echo "cache_peer 192.168.33.23 parent 8080 7 no-query no-netdb-exchange";       echo "never_direct allow all";     } >> /etc/squid/squid.conf
 ---> Running in 1d6f2d20160e
Removing intermediate container 1d6f2d20160e
 ---> f24da713ae42
Step 5/6 : EXPOSE 3128
 ---> Running in ac90cbd1e261
Removing intermediate container ac90cbd1e261
 ---> 5bc1a6aecb60
Step 6/6 : CMD /usr/sbin/squid -N -f /etc/squid/squid.conf
 ---> Running in 3c8415dcd16e
Removing intermediate container 3c8415dcd16e
 ---> 5df56d944119
Successfully built 5df56d944119
Successfully tagged docker-squid:1

作成したイメージを確認してみると、「docker-squid」のイメージが作成された。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker-squid        1                   5df56d944119        18 seconds ago      275MB
centos              7.6.1810            f1cb7c7d58b7        14 months ago       202MB

コンテナ作成

作成したイメージからコンテナを作成する。systemctlを使う場合はdocker runコマンド実行時に--privilegedオプションが必要だったが、今回はsystemctlを使用しないため不要となる。

# docker run -d -p 8080:3128 --name "docker-squid" docker-squid:1
96b890f0e14df96a433014cd42eecc37d587aa210dd92846840d02268c7e06ca

docker psコマンドでコンテナを確認する。コンテナが正常に起動していることを確認できる。

# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
96b890f0e14d        docker-squid:1      "/bin/sh -c '/usr/sb…"   7 seconds ago       Up 6 seconds        0.0.0.0:8080->3128/tcp   docker-squid

動作確認

実際にコンテナにログインして、設定状況などを確認してみよう。

まず、squid.confを確認すると、必要な設定が追記されていることが確認できる。

# docker exec -it docker-squid bash
[root@96b890f0e14d /]# cat /etc/squid/squid.conf
#
# Recommended minimum configuration:
#

~(中略)~

acl localnet src 192.168.33.0/24
acl localnet src 192.168.11.0/24

~(中略)~

cache_peer 192.168.33.23 parent 8080 7 no-query no-netdb-exchange
never_direct allow all

squidのプロセスも問題なく起動している。

[root@96b890f0e14d /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
squid        1     0  0 09:12 ?        00:00:00 /usr/sbin/squid -N -f /etc/squid/squi
squid        6     1  0 09:12 ?        00:00:00 (logfile-daemon) /var/log/squid/acces
root        27     0  0 09:15 pts/0    00:00:00 bash
root        42    27  0 09:16 pts/0    00:00:00 ps -ef

最後に、ホストOSの8080番ポートにてプロキシが正常に機能していることを確認してみる。curlコマンドを使って確認すると「HTTP/1.1 200 OK」が返ってきており、正常に動作していることが確認できた。

# export http_proxy=https://127.0.0.1:8080
# export https_proxy=https://127.0.0.1:8080
# curl -v http://www.google.co.jp
* About to connect() to proxy 127.0.0.1 port 8080 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET http://www.google.co.jp/ HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.google.co.jp
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK

~(以下略)~

まとめ

前回は手作業で実施していたコンテナ作成後の各種処理をDockerfileにて自動化することができた。Dockerfileは、参考サイトに記載した「Dockerfile のベストプラクティス」に、各種ベストプラクティスがまとめられているので、作成する際には一読しておいたほうがよいだろう。

参考

0 件のコメント:

コメントを投稿

人気の投稿