今回はDcokerコンテナについて概要から実際の使い方までをまとめてみたいと思います。
ここ最近、クラウド環境でもDockerを使ったサービスが増えており、徐々にDockerコンテナを使ったシステム構築が当たり前になってきていると思います。
今後、開発案件にもDockerコンテナを使ったものが増えていくと思われますので、改めて学習しておきましょう。

Dockerコンテナとは

Dockerコンテナは2013年ごろから存在する仮想化技術です。
それまでの仮想化技術はVMWareに代表されるように仮装PC上で実際のOSを動かすというものでした。
当初はクラウドサービスは存在せず、システムは何らかのハードウェア(サーバー)上で動作させていました。
多くの案件を保守する場合などは、それだけ多くのハードウェアが必要となり、保守するためには同数の検証用ハードウェアが必要となります。
ひとつのハードウェアで複数のシステムを保守する場合は、必要に応じてOSイメージをハードウェアにインストールして行う方法もありましたが、インストールにかなりの時間が必要になることと、ハード構成(CPU32bit, 64bitやメモリサイズ)の違いでイメージが戻せなかったりしたため、あまり有効な方法ではありませんでした。
そういった状況だったため仮想ハードウェアは非常に有用な仕組みとして多くのシステム開発で使用されていました。

その後、この仮想化技術を本番環境として利用するという動きがではじめ、複数のシステムを一つのハードウェアで運用するようになり、プライベートクラウド、クラウドサービスとなっていきました。
クラウド上でのシステム運用となると、当初必要だったハードウェアの再現が不要となり、ストレージやUSBなどの制御に関する機能などは余分なコストがかかるだけでメリットが見出せない機能となってしまいました。
そこで、そういった余計な機能を極力減らしてシステム運用に必要な機能のみを残した仮想技術としてDockerコンテナが開発されたということです。
(ちょっと想像を含んでますが。。。)

Dockerコンテナの構造

これは仮想PCとDockerコンテナの構造の比較です。
仮想PCにはハードウェアをエミュレートする機能が備わっており、ゲストOSはあたかもハードウェアを制御しているように動作していますが、実際は仮想ハードウェアを制御しているだけです。
もちろん不要な制御処理も多く存在しますのでかなり無駄が多い構造といえます。
Dockerコンテナの場合、OSカーネル処理をホストOSのOSカーネルを利用しています。
その関係でハードウェア制御などの処理は仮想OS側で実行する必要はありません。
それによってハードウェアエミュレーションは必要なく全体に簡素で効率のいい構成となっています。

DockerコンテナOSはちょっと特殊

仮想PCのゲストOSは通常のハードウェアにインストールするのと同じ手順で、OSインストーラでインストールできます。
それに対してDockerコンテナのOSはカーネルを外だししている関係で通常のインストーラでのインストールができません。
そのため、DockerコンテナはDockerなどで公開されているOSイメージをダウンロードして作成することになります。

WidnwosとDocker

Dockerは基本的にWindowsホストOS上ではWindowsイメージ、LinuxホストOS上ではLinuxイメージしか動かすことはできません。
前述の通り、DockerはOSカーネルをイメージ内に持っておらず、ホストOSのカーネルを利用して動作するため、このような制限が発生します。
2016年にHiper-Vを利用してWindows上でLinuxイメージを動かせるようになりましたが、Hiper-Vを使うことにいろいろ制約があるため使いにくさがありました。
2019年にWindows上でWSL2をインストールすることで、LinuxDockerイメージを動かせれるようになったようです。

Dockerを使ってみよう

とはいえ、やはりWindowsホストOSでDockerを構築するのはあまりないようですし、いろいろとハードルがありそうなので、今回はUbuntuをホストOSとしてDocker環境を作る手順を紹介します。

今回は(実機を用意するのが大変なので)ViretualBox上のUbuntuをホストOSとしたPC上に、RHEL9(RedHat9)の無償版(?)のUBI9をゲストOSとした環境を構築していきたいと思います。

UBIであれば、業務で使用することもできると思います。
UBIはCentOSの開発終了後に公開されるようになったDockerコンテナ用のRHELです。商用利用も可能で使い方によってはサポートもしてもらえるようです。配布も可能なようですが、ライブラリのライセンスには注意が必要なようです。実際に使う時にはライセンスを再確認していただいたほうがいいと思います。

アプリ構成はPython3.9上でFlaskを使用したアプリを作成し、Nginx-Uinitで別コンテナのNginxに連携、NginxでホストOS外のブラウザからのアクセスを可能にするという内容です。
このような構成を作成するためにPythonやNginxをインストール済みのイメージがDockerから提供されているのですが、このイメージはDebianを利用していることもあり、実際の業務で利用するにはちょっと。。。というものなので、今回はRedHat9を使用した構築手順としました。
今回使用するUBI9はRedHatから提供されている配布可能なRedHat9のDockerイメージです。
全体構成は以下の通り。

Dockerコンテナ構築準備

まずは、Dockerをインストールしましょう。
Linuxをホストとする場合、古いものが既にインストールされている場合があるので削除します。

sudo apt-get remove docker docker-engine docker.io containerd runc

アップデートと、インストールに必要なライブラリをインストールします。

sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Dockerの公式GPGキーを取得します。

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Dockerをインストールします。

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

イメージを実行して、Docker エンジンのインストールが成功したことを確認します。

sudo docker -v

確認用のイメージを起動して確認することもできます。

sudo docker run hello-world

ホストOSを再起動したときはDockerサービスが起動していないことがあるので、起動してから使いましょう。

sudo systemctl start dockerr

Dockerの仕組み

DockerコンテナはDockerやRHELなどのベンダーが提供しているイメージをダウンロードして利用します。
Dockerは(おそらく)Gitを内包しており、Dockerイメージは各ベンダーのGitからダウンロード(Pull)して使用します。
ダウンロードしたイメージはDocker内のローカルGitで保持されており、実際に構築するときはローカルGitからコピー(Clone?)して使用します。
このあたりの処理はDockerが勝手に実行するので意識する必要はありませんが、「イメージを更新したのに変わらない」といった現象が起きたときにこういった構造だということを念頭に調査するとよいと思います。
Dockerサービスは以下のような処理を”run”コマンドだけで実行しますが、ビルド(構築)のみ行うこともできます。
過去にイメージのダウンロードなどが行われている場合はローカルに保存したものを使用したり、変更箇所のみ使用してイメージを再構築するなど、それぞれの処理が早く完了するような仕組みになっています。

Dockerfileを作る前に

Dockerコンテナは通常Dockerfileを作成し、Dockerfileを使って構築を行います。
Dockerfileは構築手順をファイル化したものですが、まずはどのような手順を行えば目的のコンテナを作れるかを検証し、そのうえでDockerfileを作成、イメージの作成という手順で構築します。

いきなりDockerfileを作成してもいいのですが、「どうやって、このファイルを作ったの?」ってなると思うので、まずはイメージ構築の検証から行ってみましょう。
早くDockerコンテナを作っちゃいたい人は読み飛ばしてもらっても大丈夫です。

Docker Networkを作っておきましょう

イメージを作成する前にネットワークを作っておきましょう。
以下のコマンドをたたくだけでできます。

sudo docker network create python-nginx-network

UBI9のイメージを使ってDockerコンテナを起動

まずは、RedHatからイメージをダウンロードするのですが、いろんなイメージが公開されているのでダウンロードできる一覧を見てみましょう。
以下のコマンドでダウンロードできるイメージの一覧が取得できます。

$sudo docker search registry.access.redhat.com/ubi | grep ubi9

ubi9/go-toolset           rhcc_registry.access.redhat.com_ubi9/go-tool…   0                    
ubi9/ubi                  rhcc_registry.access.redhat.com_ubi9/ubi        0                    
ubi9                      rhcc_registry.access.redhat.com_ubi9            0                    
ubi9-beta/ubi-init        Provides the latest release of the Red Hat U…   0                    
ubi9-beta/ubi-micro       Provides the latest release of Micro Univers…   0                    
ubi9/ubi-minimal          rhcc_registry.access.redhat.com_ubi9/ubi-min…   0                    
ubi9/ubi-micro            rhcc_registry.access.redhat.com_ubi9/ubi-mic…   0                    
ubi9-minimal              rhcc_registry.access.redhat.com_ubi9-minimal    0                    
ubi9-beta/ubi             Provides the latest release of Red Hat Unive…   0                    
ubi9-beta/ubi-minimal     Provides the latest release of the Minimal R…   0                    
ubi9/ubi-init             rhcc_registry.access.redhat.com_ubi9/ubi-init   0                    
ubi9-init                 rhcc_registry.access.redhat.com_ubi9-init       0                    
ubi9-micro                rhcc_registry.access.redhat.com_ubi9-micro      0                    
ubi9-beta/toolbox         Toolbox containerized shell image based in U…   0                    
ubi9/toolbox              rhcc_registry.access.redhat.com_ubi9/toolbox    0                    
ubi9/openjdk-11-runtime   rhcc_registry.access.redhat.com_ubi9/openjdk…   0                    
ubi9/openjdk-17-runtime   rhcc_registry.access.redhat.com_ubi9/openjdk…   0                    
ubi9/openjdk-21-runtime   rhcc_registry.access.redhat.com_ubi9/openjdk…   0                    

UBIは7~9が公開されているようですので対象のバージョンの一覧を表示して使うイメージを選択してください。
今回は”ubi9/ubi”を使用します。
使用するイメージが決まったらプルします。

sudo docker pull registry.access.redhat.com/ubi9/ubi

プルは一度行えばファイル保存されるので毎回行う必要はありません。
イメージが取得できたので起動してみましょう。

sudo docker run -it -d -p 8080:8080 --name python_server \
--privileged \
--network python-nginx-network \
registry.access.redhat.com/ubi9/ubi:latest \
/sbin/init

“run”コマンドはイメージの構築と実行を同時に行います。
“-d”オプションを付けているのでデーモンとして起動してコンソールは帰ってきます。
起動できているかどうかなど、Dockerコンテナの制御は以下のコマンドで確認できます。
コンテナ名は”–name”で指定した名前です。今回は”python_server”です。
ネットワーク(“–network python-nginx-network”)や公開ポート(“-p 8080:8080”)も設定しておきます。

# コンテナ一覧(以下は同じ結果。status=up..が起動中)
sudo docker ps -a
# イメージ一覧
sudo docker images
# コンテナ停止
sudo docker stop python_server
# コンテナ起動
sudo docker start python_server
# コンテナ再起動
sudo docker restart python_server

# コンテナ削除
sudo docker rm --force [コンテナ名]
# コンテナ一括削除
sudo docker rm --force `sudo docker ps -a -q`

# イメージ削除
sudo docker rmi -f [イメージID]
# 全イメージ一括削除
sudo docker rmi -f `sudo docker images -q`

起動状態については”status”が”up …”となっていれば起動しています。

python_serverイメージを手動で構築してみる

Dockerコンテナの起動ができたのでインストール作業をしてみましょう
まずはpython環境を作っていきます。
以下のコマンドでDockerコンテナの中にコンソールで入ってインストールします。

# 起動中コンテナに入る
sudo docker exec -it python_server /bin/bash

以下の手順でガンガンインストールしましょう。

Python、その他もろもろインストール

yum -y install python39 python3-pip wget yum-utils make gcc openssl-devel bzip2-devel libffi-devel zlib-devel tar nano

nginx-unitをインストールするにはyumの設定を追加する必要があります。
以下のテキストファイルを作成します。

nano /etc/yum.repos.d/unit.repo
[unit]
name=unit repo
baseurl=https://packages.nginx.org/unit/rhel/$releasever/$basearch/
gpgcheck=0
enabled=1

nginx-unitをインストールします。

yum install -y unit-devel unit-go unit-jsc8 unit-jsc11 unit-perl unit-php unit-python39 unit-wasm

作業フォルダを作ります。

mkdir -p /usr/src/testapp

pythonライブラリインストール用のファイルを作成します。

nano /usr/src/requirements.txt
Flask

pythonライブラリをインストールします。

python3 -m pip install --upgrade pip setuptools wheel
pip3 install --no-cache-dir -r /usr/src/requirements.txt

nginx-unitの設定ファイルを作ります。

nano /usr/src/unit.config
{
        "applications": {
                "example_python": {
                        "type": "python 3.9",
                        "processes": 2,
                        "path": "/usr/src/testapp",
                        "module": "wsgi",
                        "callable": "app"
                }
        },

        "listeners": {
                "*:8080": {
                        "pass": "applications/example_python"
                }
        }
}

pyファイルを作ります。

nano /usr/src/testapp/wsgi.py
from flask import Flask

# デフォルトは"applicateion"、デフォルト以外を指定するときは"unit.config"の"callable"で指定
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

# Pythonコマンドで起動するときは以下が必要
# if __name__ == "__main__":
#     # webサーバー立ち上げ
#     app.run()

nginx-unitを起動してみる。

unitd --log /var/log/unit/unit.log --pid /var/run/unit/unit.pid

デフォルトでデーモン起動します。デーモン起動したくないときは”–no-daemon”を付けます。
起動状態はログを確認しましょう。

tail /var/log/unit/unit.log

nginx-unitにunit.configを設定します。
(普通に設定ファイルを読み込んで起動してくれればいいのに。。。)

curl -X PUT --data-binary @/usr/src/unit.config --unix-socket /var/run/unit/control.sock localhost/config/

Errorが帰ってこなければ大丈夫です。Errorの場合は上記のログで確認しましょう。
設定内容については以下で確認できます。

curl --unix-socket /var/run/unit/control.sock localhost/config/

nginx-unitが起動出来たら以下でFlaskアプリがちゃんと結果を返すか確認してみましょう。

curl http://localhost:8080

設定ファイルとかのサンプルがnginx-unitインストール時にインストールされるので、困ったときは見てみるといいと思います。

/usr/share/doc/unit-python39/examples/unit.config
/usr/share/doc/unit-python39/examples/python-app/wsgi.py

nginx_serverイメージを手動で構築してみる

python_serverと同様にイメージを作成して起動しましょう。

sudo docker run -it -d -p 80:80 --name nginx_server \
--privileged \
--network python-nginx-network \
registry.access.redhat.com/ubi9/ubi:latest \
/sbin/init

コンテナに入っていろいろインストールします。

sudo docker exec -it nginx_server /bin/bash
yum install -y --disableplugin=subscription-manager nginx nano gettext

作業フォルダを作成します。

mkdir -p /var/www/html

固定HTMLを作成します。(必要じゃないけど動作確認用)

nano /var/www/html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
</head>
<body>
    <h1>Index</h1>
    Nginx !!
</body>
</html>

設定ファイルテンプレートを作成

mkdir -p /etc/nginx/templates
nano /etc/nginx/templates/nginx.conf.template

worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    server_tokens off;

    keepalive_timeout  65;

    #gzip  on;

    upstream unit-python {
        server ${APSV_HOST}:${APSV_PORT};
    }
    server {
        listen 80;
        server_name localhost;

        location  /html {
            root /var/www;
        }

        location  / {
            proxy_pass http://unit-python;
            proxy_set_header Host $host;
        }
        location /static/ {
            alias /app/static/;
        }
    }
}

環境変数を設定してテンプレートファイルから設定ファイルを生成します。(直接設定ファイルを作ってもいいです。)

export APSV_HOST='python_server'
export APSV_PORT='8080'
cat /etc/nginx/templates/nginx.conf.template | envsubst '${APSV_HOST},${APSV_PORT}'  > /etc/nginx/nginx.conf

nginxを起動します。

nginx -c /etc/nginx/nginx.conf

デーモン起動します。デーモン起動したくないときは以下のコマンドで起動します。

nginx -g "daemon off;" -c /etc/nginx/nginx.conf

起動状態はログで確認しましょう。

cat /var/log/nginx/error.log

アクセスして確認してみましょう。

curl http://localhost

ホストOSのブラウザからアクセスして表示されれば成功です。

Dockerfileを作ってイメージを作成しよう。

Dockerコンテナ構築の手順ができたので、手順をDockerfileにしていきましょう。
python_serverのDockerfileは以下のようになります。

イメージ作成に必要なファイルを作成します

今までの手順で作成したファイルをホストに作成し、Dockerfileでイメージにコピーするようにします。

python_serverに必要なファイルを作成します

nano python/unit.repo
[unit]
name=unit repo
baseurl=https://packages.nginx.org/unit/rhel/$releasever/$basearch/
gpgcheck=0
enabled=1
nano python/unit.config
{
        "applications": {
                "example_python": {
                        "type": "python 3.9",
                        "processes": 2,
                        "path": "/usr/src/testapp",
                        "module": "wsgi",
                        "callable": "app"
                }
        },

        "listeners": {
                "*:8080": {
                        "pass": "applications/example_python"
                }
        }
}
nano python/wsgi.py
from flask import Flask

# デフォルトは"applicateion"、デフォルト以外を指定するときは"unit.config"の"callable"で指定
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

# Pythonコマンドで起動するときは以下が必要
# if __name__ == "__main__":
#     # webサーバー立ち上げ
#     app.run()
nano python/requirements.txt
Flask

Dockerコンテナ同様のシェルを作成します。
本来は”unitd”を起動するためのコマンドをDockerfileで指定するのですが、”unitd”の場合、起動後に設定ファイルを読み込ませる必要があるため、デーモンとして起動し、その後に設定ファイルを読み込ませるシェルを起動するようにします。
シェルが終了してしまうとDockerコンテナも終了してしまうので、最後に終了しないように無限ループするようにします。

nano python/unit.sh
#!/bin/sh
unitd --log /var/log/unit/unit.log --pid /var/run/unit/unit.pid
curl -X PUT --data-binary @/usr/src/unit.config --unix-socket /var/run/unit/control.sock localhost/config/
while true; do sleep 1; done

上記で作成したファイルを使用するDockerfileを作成します。

nano python/Dockerfile
FROM registry.access.redhat.com/ubi9/ubi:latest

# python3 pip3 install
RUN yum -y install python39 python3-pip wget yum-utils make gcc openssl-devel bzip2-devel libffi-devel zlib-devel tar nano

# nginx unit install
COPY ./unit.repo /etc/yum.repos.d/
RUN yum install -y unit-devel unit-go unit-jsc8 unit-jsc11 unit-perl unit-php unit-python39 unit-wasm && \
    yum clean all

# create work folder
RUN mkdir -p /usr/src/testapp

# nginx-unit setting file
COPY ./unit.config /usr/src/

# python source file
COPY ./wsgi.py /usr/src/testapp/

# python library install file
COPY ./requirements.txt /usr/src/

RUN python3 -m pip install --upgrade pip setuptools wheel && \
    pip3 install --no-cache-dir -r /usr/src/requirements.txt

COPY ./unit.sh /usr/src/
RUN chmod 755 /usr/src/unit.sh

EXPOSE 8080/tcp

CMD ["/usr/src/unit.sh"]

python_serverコンテナの構築と起動します

ファイルの準備ができたのでコンテナの構築を行って起動してみましょう。

sudo docker build -t python_server:latest ./python
sudo docker container create -it \
-p 8080:8080 \
--net python-nginx-network \
--name python_server \
--privileged \
python_server:latest
sudo docker start python_server

nginx_serverに必要なファイルを作成します

同様にnginx_server用のファイルも作成します。

# 作業フォルダを作成
mkdir nginx
nano nginx/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
</head>
<body>
    <h1>Index</h1>
    Nginx !!
</body>
</html>
nano nginx/nginx.conf.template
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    server_tokens off;

    keepalive_timeout  65;

    #gzip  on;

    upstream unit-python {
        server ${APSV_HOST}:${APSV_PORT};
    }
    server {
        listen 80;
        server_name localhost;

        location  /html {
            root /var/www;
        }

        location  / {
            proxy_pass http://unit-python;
            proxy_set_header Host $host;
        }
        location /static/ {
            alias /app/static/;
        }
    }
}

Dockerfileを作成します。

nano nginx/Dockerfile
FROM registry.access.redhat.com/ubi9/ubi:latest

RUN yum install -y --disableplugin=subscription-manager nginx nano gettext && \
    yum clean all


RUN mkdir -p /var/www/html

COPY ./index.html /var/www/html/

RUN mkdir -p /etc/nginx/templates
COPY ./nginx.conf.template /etc/nginx/templates/

ENV APSV_HOST=python_server
ENV APSV_PORT=8080
RUN cat /etc/nginx/templates/nginx.conf.template | envsubst '${APSV_HOST},${APSV_PORT}'  > /etc/nginx/nginx.conf

EXPOSE 80/tcp

CMD ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]

nginx_serverコンテナの構築と起動します

Dockerコンテナを構築して起動してみましょう。

sudo docker build -t nginx_server:latest ./nginx
sudo docker container create -it \
-p 80:80 \
--network python-nginx-network \
--name nginx_server \
--privileged \
nginx_server:latest
sudo docker start nginx_server

“docker ps”コマンドでそれぞれのDockerコンテナが起動していることを確認しましょう。
正常に起動しているようなら実際にアクセスして動きを確認しましょう。

curl http:localhost

docker-compose してみる

Dockerfileでの構築ができたので”docker-compose”を使ってみましょう。

“docker-compose”は複数のDockerコンテナを同時に構築、起動などの制御を行うツールです。

上記で作成したDockerコンテナをまとめて制御してみましょう。

docker-compose.ymlを作成します

“docker-compose”を実行するための設定ファイルを作ります。

nano docker-compose.yml
version: "3"

services:
    ap:
        build:
            context: ./python/
        ports:
            - 8080:8080
        environment:
            TZ: "Asia/Tokyo"
        container_name: python_server
    web:
        build: ./nginx
        ports:
            - 80:80
        expose:
            - 80
        environment:
            APSV_HOST: "python_server"
            APSV_PORT: "8080"
            TZ: "Asia/Tokyo"
        container_name: "nginx_server"
        depends_on:
            - ap

docker-composeで起動してみましょう

コンテナを起動します。

docker compose up -d

これで”python_server”と”nginx_server”が起動します。
“docker ps”などで起動状態を確認してみてください。
“docker-compose”には以下のようなコマンドがあります。

# コンテナの停止
docker compose stop
# コンテナの停止と削除
docker compose down
# コンテナの起動
docker compose start
# イメージビルド
docker compose build

実はdocker-compose.ymlはDockerfileと同等のことができるぐらいの機能を持っています。
今回はDockerfileにイメージ構築のほとんどの設定を入れていますが、Dockerfileには載せずにdocker-compose.ymlにほとんどの設定を乗せることもできます。
どちらにどのような設定を入れるかはユースケースによって検討してください。

まとめ

今回はDockerコンテナを使ってWebアプリケーションを作る手順を紹介しました。

最後に紹介したdocker-composeはAWSなどのクラウドの仕組みで使えないことがあります。
docker-composeは便利なので、そちらにイメージ構築の内容を多く載せてしまうとクラウドに乗せるときにDockerfileに移植しなければいけなくなってしまうことがあるので、私は基本的にDockerfileで構築するようにしています。
デプロイ先によってイメージの設定を変えたいときなどはdocker-composeで設定したほうがいい場合もありますので、用途に応じて設定内容を検討していただけるといいと思います。

次回はkubernetesについて紹介したいと思います。