Docker

【初心者向け】今更だけどDockerを使ってコンテナでアプリケーションを構築したい

ご挨拶

お疲れ様です。寺井です。

先日開催された「AWS Summit Tokyo 2023」からもう1週間が経ったんですね。
まだ余韻に浸っていて、本当に楽しかったんだなと思います。

振り返ってみると、様々な場面でコンテナ関連のお話を耳にすることが多かったと感じています。

~~~
「オンプレからECSに乗せ換えたい」
「ECS等のコンテナ関連の事例は?」
「やっぱEC2よりECSだよな?!」
「コンテナダイスキ」
~~~

私自身まだほとんど触れたことがなかったので、話を深掘りできなかったのが心残りでした。

ということでまずは「コンテナとは何ぞや?」というところから始めて、
Dockerで何かしらのアプリを動かしてみようと思います!!

コンテナとは?

AWSにおいて、コンテナ化には以下のようなメリットがあるとのこと。

  • ポータビリティ
    • プログラムコードを書き換えることなく、複数の環境にアプリケーションをデプロイできる
  • スケーラビリティ
    • 軽量で効率的に動作し、異なるアプリケーションのために単一のマシン上で複数のコンテナを簡単に追加できる
  • 耐障害性
    • 分離されたユーザースペースで動作するため、障害が発生しても他のコンテナに影響が及ばず、アプリケーションの回復力と可用性が向上する
  • 俊敏性
    • 分離された環境で実行されるため、他のサービスに干渉せず、アプリケーションコードのトラブルシューティングや変更が容易であり、ソフトウェアのリリースサイクルを短縮し、更新に迅速に対応することができる

参考:コンテナ化とは? - AWS

Dockerとは?

Dockerは、アプリケーションを標準化されたコンテナにパッケージ化し、構築、テスト、デプロイを迅速に行うことができるソフトウェアプラットフォームである。コンテナには必要なライブラリ、システムツール、コード、ランタイムなどが含まれており、どのような環境でもアプリケーションを実行できる。
参考:Docker とは | AWS

環境の移行がしやすくなり、回復力、可用性、スケーラビリティも向上すると。
めちゃくちゃ良いですね。(語彙力)

やってみる

コンテナとDockerの雰囲気は掴めたので、手を動かして実際に触ってみます。

今回のゴール

実際に動くもの(アプリとか)が無いとモチベーションが上がらないので、Pythonを使ってテキスト差分検出アプリを作成しました。

これをDocker環境で実行して、問題なく動作することを今回のゴールとします。

手順

  1. サーバー(EC2)を立てる
  2. Dockerが実行できるようにする
  3. アプリケーションを載せる
  4. 動作確認

前提

  • OS:Amazon Linux 2
  • 全て東京リージョンを利用
  • VPC、サブネット、ルートテーブル、セキュリティグループは設定済

今回はDockerに焦点を当ててお話しますので、VPC周りやEC2の起動に関する説明は省略します。

実施

最初に日本語化とタイムゾーンの設定を行っています。
(今回は検証のためrootユーザーにて実行していますが、必要に応じて「sudo」を付けて実行してください。)

#日本語化
localectl set-locale LANG=ja_JP.UTF-8
source /etc/locale.conf

#タイムゾーン変更
timedatectl set-timezone Asia/Tokyo

Dockerのインストール

念のためyumのアップデートをしてから、amazon-linux-extrasで「Docker」がインストールできるか確認します。

yum update -y

amazon-linux-extras list |grep docker
20  docker=latest            enabled      \

Dockerインストール

問題なさそうなので「amazon-linux-extras」を使用して最新の「Docker」パッケージをインストールします。

amazon-linux-extras install docker
=====================================================================================================================
 Package                 アーキテクチャー    バージョン                         リポジトリー                    容量
=====================================================================================================================
インストール中:
 docker                  x86_64              20.10.23-1.amzn2.0.1               amzn2extra-docker               41 M
依存性関連でのインストールをします:
 containerd              x86_64              1.6.19-1.amzn2.0.1                 amzn2extra-docker               27 M
 libcgroup               x86_64              0.41-21.amzn2                      amzn2-core                      66 k
 pigz                    x86_64              2.3.4-1.amzn2.0.1                  amzn2-core                      81 k
 runc                    x86_64              1.1.4-1.amzn2.0.1                  amzn2extra-docker              2.9 M

トランザクションの要約
=====================================================================================================================
インストール  1 パッケージ (+4 個の依存関係のパッケージ)
~
インストール:
  docker.x86_64 0:20.10.23-1.amzn2.0.1

依存性関連をインストールしました:
  containerd.x86_64 0:1.6.19-1.amzn2.0.1     libcgroup.x86_64 0:0.41-21.amzn2     pigz.x86_64 0:2.3.4-1.amzn2.0.1
  runc.x86_64 0:1.1.4-1.amzn2.0.1

無事インストールが完了しました。

Docker起動&有効化

サービスの起動と有効化を行います。

systemctl start docker
systemctl enable docker
systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since 金 2023-04-28 11:19:33 JST; 4s ago
     Docs: https://docs.docker.com
 Main PID: 2774 (dockerd)
   CGroup: /system.slice/docker.service
           mq2774 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --default-ulimit nofile=3...

 4月 28 11:19:33 ip-10-0-1-91.ap-northeast-1.compute.internal dockerd[2774]: time="2023-04-28T11:19:33.487477080...c
︙

「Active: active (running)」と表示されていればOKです。

Dockerグループ設定

Dockerをインストールすると、OSに「docker」グループが自動作成されます。

grep docker /etc/group
docker:x:992:

ユーザーがdockerグループに所属していない場合、Dockerデーモンへのアクセスが制限されます。

# ec2-userで実行
docker info
# エラー内容
Server:
ERROR: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/info": dial unix /var/run/docker.sock: connect: permission denied
errors pretty printing info

必要に応じてユーザーをdockerグループに追加します。

# ec2-userで実行
sudo usermod -a -G docker $USER
grep docker /etc/group
docker:x:992:ec2-user

再ログイン等を行い設定が反映されると、エラーが発生することなく実行できるようになります。

# ec2-userで実行
docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc., 0.0.0+unknown)

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 20.10.23
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk s                                     yslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 1e1ea6e986c6c86565bc33d52e34b81b3e2bc71f
 runc version: 5fd4c4d144137e991c4acebb2146ab1483a97925
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 5.10.177-158.645.amzn2.x86_64
 Operating System: Amazon Linux 2
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 927.8MiB
 Name: ip-10-0-1-91.ap-northeast-1.compute.internal
 ID: CF2W:YHQM:6KBM:YKPI:4OOV:6OAB:G4M7:27RQ:JRCO:GRE7:RYR7:IG3R
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

設置するコンテンツ(アプリケーション)の準備

今回設置するアプリケーションのディレクトリ構造

my_app/
    ├── app/
    │   ├── __init__.py
    │   ├── main.py
    │   ├── logic.py
    │   ├── templates/
    │   │   ├── index.html
    │   │   └── result.html
    │   └── static/
    │       ├── css/
    │       └── js/
    ├── Dockerfile
    ├── requirements.txt
    └── .gitignore

バックエンドにPythonを使用したウェブアプリケーションの想定です。

Dockerの基本的なコマンド一覧

これだけおさえておけば動かせそうな、基本的なコマンドをまとめました。

  1. イメージのビルド:
    docker build -t {image-name}:{tag} {path-to-dockerfile}
    • Dockerfileがあるディレクトリでこのコマンドを実行してイメージをビルドする
    • {image-name}と{tag}は任意の名前とタグを指定する
    • {path-to-dockerfile}は「Dockerfile」があるディレクトリへのパスを指定する
  2. イメージのリスト表示:
    docker images
    • ローカルに存在するすべてのDockerイメージを表示
  3. コンテナの作成と起動:
    docker run -d -p {host-port}:{container-port} --name {container-name} {image-name}:{tag}
    • イメージを元に新しいコンテナを作成して実行する
    • {host-port}と{container-port}でホストとコンテナのポートをマッピングする
    • {container-name}でコンテナに任意の名前を付け{image-name}と{tag}で実行するイメージを指定する。
  4. コンテナのリスト表示:
    docker ps
    • 現在実行中のコンテナを表示する
    • すべてのコンテナ(実行中のものと停止しているもの)を表示するには「docker ps -a」を使用する
  5. コンテナの停止:
    docker stop {container-name-or-id}
    • 指定されたコンテナを停止する
    • {container-name-or-id}で停止するコンテナの名前またはIDを指定する
  6. コンテナの削除:
    docker rm {container-name-or-id}
    • 指定されたコンテナを削除する
    • {container-name-or-id}で、削除するコンテナの名前またはIDを指定する
  7. イメージの削除:
    docker rmi {image-name}:{tag}
    • 指定されたイメージを削除する
    • {image-name}と{tag}で削除するイメージを指定する
  8. コンテナのログの表示:
    docker logs {container-name-or-id}
    • 指定されたコンテナのログを表示する
    • {container-name-or-id}でログを表示するコンテナの名前またはIDを指定する

「Dockerfile」について

Dockerfileは、Dockerイメージのビルドプロセスを定義するテキストファイル

ベースイメージの選択、環境変数の設定、ファイルのコピー、パッケージのインストール、ポートの公開など、イメージの作成に必要な手順記述するものです。

実際の中身はこんな感じになります。

# ベースイメージを指定します。これは、ビルドプロセスの最初に実行される命令です。
FROM python:3.9

# コンテナ内で作業するディレクトリを設定します。
WORKDIR /app

# ホストシステムのファイルやディレクトリをコンテナにコピーします。
COPY requirements.txt requirements.txt
COPY ./app /app

# シェルコマンドを実行します。これは、パッケージのインストールやファイルの編集などに使用されます。
RUN python -m pip install --upgrade pip
RUN pip install -r requirements.txt

# 環境変数を設定します。
ENV DB_NAME="test_db"

# コンテナが実行されるときにデフォルトで実行されるコマンドを設定します。ただし、docker runコマンドで別のコマンドが指定された場合、CMDで指定されたコマンドは上書きされます。
CMD ["python", "main.py"]

Dockerイメージのビルド

「app/~」のアプリケーションデータを「Dockerfile」を使用してDockerイメージとしてビルドします。

docker build -t my_app .
Sending build context to Docker daemon  17.92kB
Step 1/8 : FROM python:3.9
3.9: Pulling from library/python
b0248cf3e63c: Pull complete
︙
Successfully built 3abf2ffcd9a1
Successfully tagged my_app:latest

ビルドが完了したようです。
Dockerイメージを確認します。

docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
my_app       latest    3abf2ffcd9a1   58 seconds ago   1.01GB
python       3.9       2202efa5d0ba   2 weeks ago      907MB

「my_app」という名前のDockerイメージが作成されています。

コンテナを作成して実行する

作成したイメージを元に新しいコンテナを作成して実行します。

docker run -p 5000:5000 --name my_app_instance my_app
オプション 内容
-p または --publish ホストマシンのポートとコンテナ内のポートをマッピング(形式は host_port:container_port)
--name コンテナに任意の名前を割り当て
 * Serving Flask app 'main' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

「127.0.0.1:5000」でコンテナにアクセスしてみると、アプリケーションが実行できていることが確認できました!!!!

コンソールではアクセスログが出力されています。

︙
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
{クライアントIPアドレス} - - [28/Apr/2023 08:28:38] "GET / HTTP/1.1" 200 -
{クライアントIPアドレス} - - [28/Apr/2023 08:28:38] "GET /static/css/style.css HTTP/1.1" 304 -

コンテナを停止&イメージの削除

まずは実行中のコンテナを確認します。

docker ps -a
CONTAINER ID   IMAGE     COMMAND            CREATED         STATUS                          PORTS     NAMES
338c907787fb   my_app    "python main.py"   5 minutes ago   Exited (0) About a minute ago             my_app_instance

「NAMES」を指定して実行中のコンテナを停止します。

docker stop my_app_instance

同じく「NAMES」を指定してコンテナを削除します。

docker rm my_app_instance

実行中のコンテナが無いことを確認します。

docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Dockerイメージは残っているので、イメージからコンテナを開始することで、いつでもアプリケーションを実行できます。

docker images
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
my_app       latest    3abf2ffcd9a1   About an hour ago   1.01GB
python       3.9       2202efa5d0ba   2 weeks ago         907MB

感想

「取り残されないようにまずは分からんなりに触ってみよう」という思いから始めたんですが、思ってた以上に楽しくて夢中になりそうです。

コンテナのスペシャリストになれるよう精進します!

次回はAWSと絡めて「ECS」や「Fargate」を触ってみたいと思います。

お疲れ様でした。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA