目次
ご挨拶
お疲れ様です。寺井です。
先日開催された「AWS Summit Tokyo 2023」からもう1週間が経ったんですね。
まだ余韻に浸っていて、本当に楽しかったんだなと思います。
振り返ってみると、様々な場面でコンテナ関連のお話を耳にすることが多かったと感じています。
~~~
「オンプレからECSに乗せ換えたい」
「ECS等のコンテナ関連の事例は?」
「やっぱEC2よりECSだよな?!」
「コンテナダイスキ」
~~~
私自身まだほとんど触れたことがなかったので、話を深掘りできなかったのが心残りでした。
ということでまずは「コンテナとは何ぞや?」というところから始めて、
Dockerで何かしらのアプリを動かしてみようと思います!!
コンテナとは?
AWSにおいて、コンテナ化には以下のようなメリットがあるとのこと。
- ポータビリティ
- プログラムコードを書き換えることなく、複数の環境にアプリケーションをデプロイできる
- スケーラビリティ
- 軽量で効率的に動作し、異なるアプリケーションのために単一のマシン上で複数のコンテナを簡単に追加できる
- 耐障害性
- 分離されたユーザースペースで動作するため、障害が発生しても他のコンテナに影響が及ばず、アプリケーションの回復力と可用性が向上する
- 俊敏性
- 分離された環境で実行されるため、他のサービスに干渉せず、アプリケーションコードのトラブルシューティングや変更が容易であり、ソフトウェアのリリースサイクルを短縮し、更新に迅速に対応することができる
Dockerとは?
Dockerは、アプリケーションを標準化されたコンテナにパッケージ化し、構築、テスト、デプロイを迅速に行うことができるソフトウェアプラットフォームである。コンテナには必要なライブラリ、システムツール、コード、ランタイムなどが含まれており、どのような環境でもアプリケーションを実行できる。
参考:Docker とは | AWS
環境の移行がしやすくなり、回復力、可用性、スケーラビリティも向上すると。
めちゃくちゃ良いですね。(語彙力)
やってみる
コンテナとDockerの雰囲気は掴めたので、手を動かして実際に触ってみます。
今回のゴール
実際に動くもの(アプリとか)が無いとモチベーションが上がらないので、Pythonを使ってテキスト差分検出アプリを作成しました。
これをDocker環境で実行して、問題なく動作することを今回のゴールとします。
手順
- サーバー(EC2)を立てる
- Dockerが実行できるようにする
- アプリケーションを載せる
- 動作確認
前提
- 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の基本的なコマンド一覧
これだけおさえておけば動かせそうな、基本的なコマンドをまとめました。
- イメージのビルド:
docker build -t {image-name}:{tag} {path-to-dockerfile}
- Dockerfileがあるディレクトリでこのコマンドを実行してイメージをビルドする
- {image-name}と{tag}は任意の名前とタグを指定する
- {path-to-dockerfile}は「Dockerfile」があるディレクトリへのパスを指定する
- イメージのリスト表示:
docker images
- ローカルに存在するすべてのDockerイメージを表示
- コンテナの作成と起動:
docker run -d -p {host-port}:{container-port} --name {container-name} {image-name}:{tag}
- イメージを元に新しいコンテナを作成して実行する
- {host-port}と{container-port}でホストとコンテナのポートをマッピングする
- {container-name}でコンテナに任意の名前を付け{image-name}と{tag}で実行するイメージを指定する。
- コンテナのリスト表示:
docker ps
- 現在実行中のコンテナを表示する
- すべてのコンテナ(実行中のものと停止しているもの)を表示するには「docker ps -a」を使用する
- コンテナの停止:
docker stop {container-name-or-id}
- 指定されたコンテナを停止する
- {container-name-or-id}で停止するコンテナの名前またはIDを指定する
- コンテナの削除:
docker rm {container-name-or-id}
- 指定されたコンテナを削除する
- {container-name-or-id}で、削除するコンテナの名前またはIDを指定する
- イメージの削除:
docker rmi {image-name}:{tag}
- 指定されたイメージを削除する
- {image-name}と{tag}で削除するイメージを指定する
- コンテナのログの表示:
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」を触ってみたいと思います。
お疲れ様でした。
好きなこと:音楽、猫、お酒、ゲーム、効率化
経歴:音楽専門学校 → テレビ業界AD → 通信回線代理店 → IT関連職業訓練 → 2022.12~ 株式会社ディーネット