目次
はじめに
こんにちは、「DENET ADVENT CALENDAR 2024」12月6日担当の山中です。
今回は、以前から気になっていた「コンテナ技術」に入門した際の内容を記事にしました。
具体的には Dockerfile を使用してフロントエンド、バックエンド、DBコンテナを構成、連携させてみた内容で、ほぼコピペで同じように3層コンテナを体験できると思うのでよければご参考いただければと思います。
事前知識
最初に、コンテナの基本的なイメージを掴むために、簡単な例を挙げて説明します。
コンテナとは
コンテナは、アプリケーションと、その設定や動作環境を1つのパッケージにまとめ、どこでも動作させられるようにした技術です。
コンテナを「弁当箱」に例えると分かりやすいかもしれません。
弁当箱には、ご飯、おかず、箸が一緒に入っています。
必要なものが全部そろっているので、どこに持って行っても同じように食べられます。
コンテナも同じで、アプリケーション(弁当)とその設定や動作環境(箸や調味料)をひとまとめにして、「どのサーバーに持っていっても動く状態」にしています。
このコンテナは、イメージと呼ばれる設計図のようなものから作成されます。
なぜ「コンテナ」が必要なのか
IT分野では、アプリケーションが「どこでも同じように動く」ことが非常に重要です。
しかし、従来の方法では以下のような問題が発生することがあります。
①開発環境では動くのに、実際のサーバーでは動かない。
②動作環境や設定の違いでサーバーごとに設定を変えるのが面倒。
こうした課題を解決し、同一の環境を手軽に準備するためにコンテナが必要とされています。
他にも以下のようなメリットがあります。
・ホストOS上のプロセスで動作するため軽量であり、数秒でコンテナの起動や終了が可能
・数秒でコンテナの起動や終了が可能なため、必要に応じて簡単にコンテナを増減できる
・コンテナは必要なものだけを含むため、サーバーのリソース消費に無駄がない
・上記メリットにより同一環境を手軽に用意できるため、開発、テスト、運用の効率化が可能など
このコンテナを簡単に管理するためのツール(プラットフォーム)として、Docker が存在します。
Docker とは
Docker はコンテナを簡単に作成・管理できるツール(プラットフォーム)です。
コンテナ技術を活用する第一歩としてよく選ばれます。
最近、Red Hat Enterprise Linux(RHEL)では Docker とほぼ同様に使用できる Podman の利用が推奨されているみたいです。
事前知識はここまでで、次は実際にコンテナを試してみた際の具体的な内容になります。
検証環境
- AlmaLinux release 8.10
- セキュリティグループ 22,80,3000 許可済み
手順
Docker 導入
Docker リポジトリ追加
最初に、Docker の公式リポジトリを追加します。
[root@con-test ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
repo の追加: https://download.docker.com/linux/centos/docker-ce.repo
追加後、リポジトリを確認します、docker-ce-stable が有効化されていればOKです。
[root@con-test ~]# dnf repolist docker*
repo id repo の名前 状態
docker-ce-nightly Docker CE Nightly - x86_64 無効化
docker-ce-nightly-debuginfo Docker CE Nightly - Debuginfo x86_64 無効化
docker-ce-nightly-source Docker CE Nightly - Sources 無効化
docker-ce-stable Docker CE Stable - x86_64 有効化
docker-ce-stable-debuginfo Docker CE Stable - Debuginfo x86_64 無効化
docker-ce-stable-source Docker CE Stable - Sources 無効化
docker-ce-test Docker CE Test - x86_64 無効化
docker-ce-test-debuginfo Docker CE Test - Debuginfo x86_64 無効化
docker-ce-test-source Docker CE Test - Sources 無効化
Docker インストール
公式リポジトリの追加が確認できたので Docker CE(Community Edition)をインストールします。
[root@con-test ~]# dnf install docker-ce docker-ce-cli containerd.io
Docker CE Stable - x86_64 789 kB/s | 66 kB 00:00
メタデータの期限切れの最終確認: 0:00:01 前の 2024年12月04日 13時29分26秒 に実施しました。
依存関係が解決しました。
=======================================================================================================================================
パッケージ Arch バージョン リポジトリー サイズ
=======================================================================================================================================
インストール:
containerd.io x86_64 1.6.32-3.1.el8 docker-ce-stable 35 M
docker-ce x86_64 3:26.1.3-1.el8 docker-ce-stable 27 M
docker-ce-cli x86_64 1:26.1.3-1.el8 docker-ce-stable 7.8 M
依存関係のインストール:
container-selinux noarch 2:2.229.0-2.module_el8.10.0+3926+f12484f5 appstream 70 k
fuse-common x86_64 3.3.0-19.el8 baseos 21 k
fuse-overlayfs x86_64 1.13-1.module_el8.10.0+3926+f12484f5 appstream 69 k
fuse3 x86_64 3.3.0-19.el8 baseos 54 k
fuse3-libs x86_64 3.3.0-19.el8 baseos 95 k
libcgroup x86_64 0.41-19.el8 baseos 69 k
libslirp x86_64 4.4.0-2.module_el8.10.0+3926+f12484f5 appstream 69 k
slirp4netns x86_64 1.2.3-1.module_el8.10.0+3926+f12484f5 appstream 55 k
弱い依存関係のインストール:
docker-buildx-plugin x86_64 0.14.0-1.el8 docker-ce-stable 14 M
docker-ce-rootless-extras x86_64 26.1.3-1.el8 docker-ce-stable 5.0 M
docker-compose-plugin x86_64 2.27.0-1.el8 docker-ce-stable 13 M
モジュールストリームの有効化中:
container-tools rhel8
トランザクションの概要
=======================================================================================================================================
インストール 14 パッケージ
ダウンロードサイズの合計: 103 M
インストール後のサイズ: 390 M
これでよろしいですか? [y/N]: y
パッケージのダウンロード:
(1/14): fuse-common-3.3.0-19.el8.x86_64.rpm 2.3 MB/s | 21 kB 00:00
(2/14): fuse3-3.3.0-19.el8.x86_64.rpm 4.6 MB/s | 54 kB 00:00
(3/14): fuse3-libs-3.3.0-19.el8.x86_64.rpm 6.0 MB/s | 95 kB 00:00
(4/14): libcgroup-0.41-19.el8.x86_64.rpm 10 MB/s | 69 kB 00:00
(5/14): container-selinux-2.229.0-2.module_el8.10.0+3926+f12484f5.noarch.rpm 7.0 MB/s | 70 kB 00:00
(6/14): fuse-overlayfs-1.13-1.module_el8.10.0+3926+f12484f5.x86_64.rpm 6.4 MB/s | 69 kB 00:00
(7/14): slirp4netns-1.2.3-1.module_el8.10.0+3926+f12484f5.x86_64.rpm 7.9 MB/s | 55 kB 00:00
(8/14): libslirp-4.4.0-2.module_el8.10.0+3926+f12484f5.x86_64.rpm 6.6 MB/s | 69 kB 00:00
(9/14): docker-buildx-plugin-0.14.0-1.el8.x86_64.rpm 49 MB/s | 14 MB 00:00
(10/14): docker-ce-cli-26.1.3-1.el8.x86_64.rpm 56 MB/s | 7.8 MB 00:00
(11/14): docker-ce-rootless-extras-26.1.3-1.el8.x86_64.rpm 37 MB/s | 5.0 MB 00:00
(12/14): docker-ce-26.1.3-1.el8.x86_64.rpm 38 MB/s | 27 MB 00:00
(13/14): containerd.io-1.6.32-3.1.el8.x86_64.rpm 33 MB/s | 35 MB 00:01
(14/14): docker-compose-plugin-2.27.0-1.el8.x86_64.rpm 22 MB/s | 13 MB 00:00
---------------------------------------------------------------------------------------------------------------------------------------
合計 42 MB/s | 103 MB 00:02
Docker CE Stable - x86_64 67 kB/s | 1.6 kB 00:00
GPG 鍵 0x621E9F35 をインポート中:
Userid : "Docker Release (CE rpm) <docker@docker.com>"
Fingerprint: 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35
From : https://download.docker.com/linux/centos/gpg
これでよろしいですか? [y/N]: y
鍵のインポートに成功しました
トランザクションを確認しています
トランザクションの確認に成功しました。
トランザクションをテストしています
トランザクションのテストに成功しました。
トランザクションを実行しています
準備中 : 1/1
インストール中 : docker-compose-plugin-2.27.0-1.el8.x86_64 1/14
scriptletの実行中: docker-compose-plugin-2.27.0-1.el8.x86_64 1/14
scriptletの実行中: container-selinux-2:2.229.0-2.module_el8.10.0+3926+f12484f5.noarch 2/14
インストール中 : container-selinux-2:2.229.0-2.module_el8.10.0+3926+f12484f5.noarch 2/14
scriptletの実行中: container-selinux-2:2.229.0-2.module_el8.10.0+3926+f12484f5.noarch 2/14
インストール中 : fuse3-libs-3.3.0-19.el8.x86_64 3/14
scriptletの実行中: fuse3-libs-3.3.0-19.el8.x86_64 3/14
インストール中 : containerd.io-1.6.32-3.1.el8.x86_64 4/14
scriptletの実行中: containerd.io-1.6.32-3.1.el8.x86_64 4/14
インストール中 : docker-buildx-plugin-0.14.0-1.el8.x86_64 5/14
scriptletの実行中: docker-buildx-plugin-0.14.0-1.el8.x86_64 5/14
インストール中 : docker-ce-cli-1:26.1.3-1.el8.x86_64 6/14
scriptletの実行中: docker-ce-cli-1:26.1.3-1.el8.x86_64 6/14
[sss_cache] [sysdb_domain_cache_connect] (0x0010): DB version too old [0.23], expected [0.24] for domain implicit_files!
Higher version of database is expected!
In order to upgrade the database, you must run SSSD.
Removing cache files in /var/lib/sss/db should fix the issue, but note that removing cache files will also remove all of your cached credentials.
Could not open available domains
[sss_cache] [sysdb_domain_cache_connect] (0x0010): DB version too old [0.23], expected [0.24] for domain implicit_files!
Higher version of database is expected!
In order to upgrade the database, you must run SSSD.
Removing cache files in /var/lib/sss/db should fix the issue, but note that removing cache files will also remove all of your cached credentials.
Could not open available domains
インストール中 : libslirp-4.4.0-2.module_el8.10.0+3926+f12484f5.x86_64 7/14
インストール中 : slirp4netns-1.2.3-1.module_el8.10.0+3926+f12484f5.x86_64 8/14
scriptletの実行中: libcgroup-0.41-19.el8.x86_64 9/14
[sss_cache] [sysdb_domain_cache_connect] (0x0010): DB version too old [0.23], expected [0.24] for domain implicit_files!
Higher version of database is expected!
In order to upgrade the database, you must run SSSD.
Removing cache files in /var/lib/sss/db should fix the issue, but note that removing cache files will also remove all of your cached credentials.
Could not open available domains
[sss_cache] [sysdb_domain_cache_connect] (0x0010): DB version too old [0.23], expected [0.24] for domain implicit_files!
Higher version of database is expected!
In order to upgrade the database, you must run SSSD.
Removing cache files in /var/lib/sss/db should fix the issue, but note that removing cache files will also remove all of your cached credentials.
Could not open available domains
インストール中 : libcgroup-0.41-19.el8.x86_64 9/14
scriptletの実行中: libcgroup-0.41-19.el8.x86_64 9/14
インストール中 : fuse-common-3.3.0-19.el8.x86_64 10/14
インストール中 : fuse3-3.3.0-19.el8.x86_64 11/14
インストール中 : fuse-overlayfs-1.13-1.module_el8.10.0+3926+f12484f5.x86_64 12/14
scriptletの実行中: fuse-overlayfs-1.13-1.module_el8.10.0+3926+f12484f5.x86_64 12/14
インストール中 : docker-ce-3:26.1.3-1.el8.x86_64 13/14
scriptletの実行中: docker-ce-3:26.1.3-1.el8.x86_64 13/14
インストール中 : docker-ce-rootless-extras-26.1.3-1.el8.x86_64 14/14
scriptletの実行中: docker-ce-rootless-extras-26.1.3-1.el8.x86_64 14/14
scriptletの実行中: container-selinux-2:2.229.0-2.module_el8.10.0+3926+f12484f5.noarch 14/14
scriptletの実行中: docker-ce-rootless-extras-26.1.3-1.el8.x86_64 14/14
検証中 : fuse-common-3.3.0-19.el8.x86_64 1/14
検証中 : fuse3-3.3.0-19.el8.x86_64 2/14
検証中 : fuse3-libs-3.3.0-19.el8.x86_64 3/14
検証中 : libcgroup-0.41-19.el8.x86_64 4/14
検証中 : container-selinux-2:2.229.0-2.module_el8.10.0+3926+f12484f5.noarch 5/14
検証中 : fuse-overlayfs-1.13-1.module_el8.10.0+3926+f12484f5.x86_64 6/14
検証中 : libslirp-4.4.0-2.module_el8.10.0+3926+f12484f5.x86_64 7/14
検証中 : slirp4netns-1.2.3-1.module_el8.10.0+3926+f12484f5.x86_64 8/14
検証中 : containerd.io-1.6.32-3.1.el8.x86_64 9/14
検証中 : docker-buildx-plugin-0.14.0-1.el8.x86_64 10/14
検証中 : docker-ce-3:26.1.3-1.el8.x86_64 11/14
検証中 : docker-ce-cli-1:26.1.3-1.el8.x86_64 12/14
検証中 : docker-ce-rootless-extras-26.1.3-1.el8.x86_64 13/14
検証中 : docker-compose-plugin-2.27.0-1.el8.x86_64 14/14
インストール済み:
container-selinux-2:2.229.0-2.module_el8.10.0+3926+f12484f5.noarch containerd.io-1.6.32-3.1.el8.x86_64
docker-buildx-plugin-0.14.0-1.el8.x86_64 docker-ce-3:26.1.3-1.el8.x86_64
docker-ce-cli-1:26.1.3-1.el8.x86_64 docker-ce-rootless-extras-26.1.3-1.el8.x86_64
docker-compose-plugin-2.27.0-1.el8.x86_64 fuse-common-3.3.0-19.el8.x86_64
fuse-overlayfs-1.13-1.module_el8.10.0+3926+f12484f5.x86_64 fuse3-3.3.0-19.el8.x86_64
fuse3-libs-3.3.0-19.el8.x86_64 libcgroup-0.41-19.el8.x86_64
libslirp-4.4.0-2.module_el8.10.0+3926+f12484f5.x86_64 slirp4netns-1.2.3-1.module_el8.10.0+3926+f12484f5.x86_64
完了しました!
インストールが完了したら Docker のバージョンを確認します。
Docker のバージョンが表示されていればインストールは完了です。
[root@con-test ~]# docker -v
Docker version 26.1.3, build b72abbb
Docker サービスの起動と自動起動設定
インストールが完了したら、Docker サービスの起動と自動起動を設定します。
[root@con-test ~]# systemctl enable --now docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
Docker の起動と自動起動を確認します。
[root@con-test ~]# 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 Wed 2024-12-04 13:32:08 JST; 13s ago
Docs: https://docs.docker.com
Main PID: 82291 (dockerd)
Tasks: 8
Memory: 41.3M
CGroup: /system.slice/docker.service
mq82291 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
12月 04 13:32:07 con-test dockerd[82291]: time="2024-12-04T13:32:07.922900218+09:00" level=info msg="Starting up"
12月 04 13:32:07 con-test dockerd[82291]: time="2024-12-04T13:32:07.967614512+09:00" level=info msg="Loading containers: start."
12月 04 13:32:08 con-test dockerd[82291]: time="2024-12-04T13:32:08.425985692+09:00" level=info msg="Loading containers: done."
12月 04 13:32:08 con-test dockerd[82291]: time="2024-12-04T13:32:08.451631236+09:00" level=info msg="Docker daemon" commit=8e96db1 con>
12月 04 13:32:08 con-test dockerd[82291]: time="2024-12-04T13:32:08.451758194+09:00" level=info msg="Daemon has completed initializati>
12月 04 13:32:08 con-test dockerd[82291]: time="2024-12-04T13:32:08.512322576+09:00" level=info msg="API listen on /run/docker.sock"
以下で「active (running)」となっていれば起動している事が確認できます。
「Active: active (running) since Wed 2024-12-04 13:32:08 JST; 13s ago」
以下で「enabled;」となっていれば自動起動が有効化されている事を確認できます。
「Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled;」
以上で Docker の導入が完了しました。
次はコンテナを用意していきます。
一般ユーザーが Docker を使うには、そのユーザーを docker グループに追加する必要があります。
今回は root ユーザーで作業しているため、こちらの設定は行っていません。
sudo usermod -aG docker $USER
コンテナ作成
以下の順でコンテナを作成していきます。
・フロントエンドコンテナ
・バックエンドコンテナ
・DBコンテナ
コンテナは Docker イメージという設計図から作成されます。
Docker hub から Docker イメージを取得すれば手早くコンテナを作成できますが、今回は Dockerfile を用意して1つずつ作成していきます。
フロントエンドコンテナ作成
最初に、フロントエンドコンテナを作成します。
frontend ディレクトリを作成します。
[root@con-test ~]# mkdir frontend
[root@con-test ~]# ll -d frontend
drwxr-xr-x 2 root root 6 12月 4 13:41 frontend
次に、frontend ディレクトリで簡単な HTML ファイルを作成します。
[root@con-test ~]# vim /root/frontend/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Frontend</title>
</head>
<body>
<h1>Frontend is running!</h1>
</body>
</html>
続いて frontend ディレクトリでフロントエンドコンテナのイメージを作成するため Dockerfile を作成します。
[root@con-test ~]# vim /root/frontend/Dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/
「FROM nginx:alpine」
軽量な NGINX(nginx:alpine イメージ)ベースの簡単な Web サーバーを構築します。
「COPY index.html /usr/share/nginx/html/」
先程作成した /root/frontend/index.html を NGINX のデフォルトの公開ディレクトリ /usr/share/nginx/html/ にコピーしています。
Dockerfile が作成できたので docker build コマンドを使用して
作成した Dockerfile から Docker イメージをビルドしていきます。
「-t」でイメージ名を指定しています。
[root@con-test ~]# docker build -t my-frontend /root/frontend
[+] Building 4.1s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 94B 0.0s
=> [internal] load metadata for docker.io/library/nginx:alpine 2.1s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 199B 0.0s
=> [1/2] FROM docker.io/library/nginx:alpine@sha256:41523187cf7d7a2f2677a80609d9caa14388bf5c1fbca9c410ba3de602aaaab4 1.6s
=> => resolve docker.io/library/nginx:alpine@sha256:41523187cf7d7a2f2677a80609d9caa14388bf5c1fbca9c410ba3de602aaaab4 0.0s
=> => sha256:b1f7437a6d0398a47a5d74a1e178ea6fff3ea692c9e41d19c2b3f7ce52cdb371 2.50kB / 2.50kB 0.0s
=> => sha256:da9db072f522755cbeb85be2b3f84059b70571b229512f1571d9217b77e1087f 3.62MB / 3.62MB 0.2s
=> => sha256:e10e486de1ab216956a771c782ef1adabef10b1bfd9a3765e14f79484784e9cd 4.06MB / 4.06MB 0.6s
=> => sha256:af9c0e53c5a430c700d068066f35cb313945c9917bee94108bae13a933f6b6b4 628B / 628B 0.3s
=> => sha256:41523187cf7d7a2f2677a80609d9caa14388bf5c1fbca9c410ba3de602aaaab4 10.36kB / 10.36kB 0.0s
=> => sha256:91ca84b4f57794f97f70443afccff26aed771e36bc48bad1e26c2ce66124ea66 11.25kB / 11.25kB 0.0s
=> => extracting sha256:da9db072f522755cbeb85be2b3f84059b70571b229512f1571d9217b77e1087f 0.1s
=> => sha256:b2eb2b8af93a0c4d2b5f5a70ed620869b406658462aba70b03f12f442aa40cc1 956B / 956B 0.5s
=> => sha256:e351ee5ec3d4f55b4e3fce972c2a34a5632ede02602dfbcad85afc539b486131 405B / 405B 0.5s
=> => extracting sha256:e10e486de1ab216956a771c782ef1adabef10b1bfd9a3765e14f79484784e9cd 0.1s
=> => sha256:471412c08d15ee3b0c86b86fe91a6dd0e17d1f4d1b6d83a7f68e9b709328bf3d 1.40kB / 1.40kB 0.8s
=> => sha256:fbbf7d28be71101773e4440c75dbbe7ed12767763fbb2e9c85a32a31f611169a 1.21kB / 1.21kB 0.7s
=> => sha256:a2eb5282fbec00fa3d13849dafbfd7f416b69059e527e5653b84f1d9245b8eb0 15.10MB / 15.10MB 0.9s
=> => extracting sha256:af9c0e53c5a430c700d068066f35cb313945c9917bee94108bae13a933f6b6b4 0.0s
=> => extracting sha256:b2eb2b8af93a0c4d2b5f5a70ed620869b406658462aba70b03f12f442aa40cc1 0.0s
=> => extracting sha256:e351ee5ec3d4f55b4e3fce972c2a34a5632ede02602dfbcad85afc539b486131 0.0s
=> => extracting sha256:fbbf7d28be71101773e4440c75dbbe7ed12767763fbb2e9c85a32a31f611169a 0.0s
=> => extracting sha256:471412c08d15ee3b0c86b86fe91a6dd0e17d1f4d1b6d83a7f68e9b709328bf3d 0.0s
=> => extracting sha256:a2eb5282fbec00fa3d13849dafbfd7f416b69059e527e5653b84f1d9245b8eb0 0.4s
=> [2/2] COPY index.html /usr/share/nginx/html/ 0.1s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:0ddf02aa6138b6c316b5947df99160d047a22a029e8b9dbff1578b66d09e06ca 0.0s
=> => naming to docker.io/library/my-frontend 0.0s
イメージが作成されたら docker images コマンドを使用してイメージ一覧を確認します。
my-frontend イメージが作成されている事が確認できます。
[root@con-test ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-frontend latest 0ddf02aa6138 About a minute ago 52.5MB
イメージの作成が確認できたので docker run コマンドを使用して my-frontend イメージからコンテナを作成していきます。
「-d」でコンテナをバックグラウンドで起動させ、
「--name」でコンテナ名を指定しています。
「-p」で 80番ポートのリクエストがフロントエンドコンテナに向くようにマッピングしています。
[root@con-test ~]# docker run -d --name frontend -p 80:80 my-frontend
b9ab79e88f2bba05ef63aa9c616c2df6b8fe2cae436f4f30093bd828669eae60
コンテナの識別IDが表示されたらOKです。
docker ps コマンドで作成されたコンテナを確認できるので frontend コンテナの作成を確認します。
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b9ab79e88f2b my-frontend "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp frontend
frontend コンテナの「STATUS」が「Up」と表示されていればOKです。
frontend コンテナの作成が確認できたのでブラウザ上からコンテナにアクセスして動作確認を行います。
ブラウザで http://<EC2のパブリックIP> にアクセスし、「Frontend is running!」が表示されれば成功です。
frontend コンテナのアクセスログを表示して、サーバ上でもアクセスに問題がない事を確認します。
docker logs コマンドを使用して frontend コンテナのアクセスログを確認できます。
[root@con-test ~]# docker logs frontend
{IP} - - [04/Dec/2024:04:59:18 +0000] "GET / HTTP/1.1" 200 160 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
{IP} - - [04/Dec/2024:04:59:18 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://13.231.3.188/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
2024/12/04 04:59:18 [error] 30#30: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 221.243.14.226, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "13.231.3.188", referrer: "http://13.231.3.188/"
GET リクエストでステータスコード:200 が出ていればOKです。
favicon.ico で 404 出ていますが、favicon.ico は用意していないのでこれは問題ないです。
フロントエンドコンテナの動作が確認できたので、次はバックエンドコンテナ(アプリケーションサーバ)を作成していきます。
バックエンドコンテナ作成
バックエンドコンテナ作成前にカスタムネットワークを作成しておきます。
後にコンテナ間を繋ぐのに必要になります。
[root@con-test ~]# docker network create my-network
6d4b7b3f66243d933d702180e2ffaa866d50a563b6ecf572be6fb4b8b6bd5762
frontend ディレクトリと同じ階層に backend ディレクトリを作成します。
[root@con-test ~]# mkdir /root/backend
[root@con-test ~]# ll -d /root/backend
drwxr-xr-x 2 root root 6 12月 4 14:08 /root/backend
backend ディレクトリで app.js を作成します。
フロントエンドとバックエンドを通信させるための処理を app.js に記載していきます。
[root@con-test ~]# vim /root/backend/app.js
const express = require('express');
const app = express();
app.get('/api/data', (req, res) => {
res.json({ message: "Hello from Backend!" });
});
app.listen(3000, () => {});
「const express = require('express');」
「const app = express();」
アプリケーションフレームワーク Express のインポートと、Express インスタンスの定義を行っています。
「app.get('/api/data', (req, res) => {
res.json({ message: "Hello from Backend!" });
});」
/api/data 宛てにリクエストが来た時「Hello from Backend!」を返すようにしています。
「app.listen(3000, () => {});」
3000番ポートでバックエンドサーバを起動させています。
backend ディレクトリでバックエンドコンテナ用のイメージを作成するための Dockerfile を作成します。
[root@con-test ~]# vim /root/backend/Dockerfile
FROM node:16
WORKDIR /app
COPY . .
RUN npm install express
CMD ["node", "app.js"]
「FROM node:16」
Node.jsのバージョン16をベースイメージとして指定しています。
「WORKDIR /app」
コンテナ内の作業ディレクトリを /app に設定しています。
「COPY . .」
先程作成した app.js 等をバックエンドコンテナの /app ディレクトリにコピーしています。
「RUN npm install express」
express インストールしています。
「CMD ["node", "app.js"] 」
バックエンドコンテナが実行された際、Node.js で app.js を実行するように指定しています。
こちらでコンテナ内でバックエンドサーバが起動されます。
バックエンドコンテナ用の Dockerfile が作成できたのでビルドしていきます。
[root@con-test ~]# docker build -t my-backend /root/backend/
[+] Building 27.9s (9/9) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load metadata for docker.io/library/node:16 1.8s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/4] FROM docker.io/library/node:16@sha256:f77a1aef2da8d83e45ec990f45df50f1a286c5fe8bbfb8c6e4246c6389705c0b 21.4s
=> => resolve docker.io/library/node:16@sha256:f77a1aef2da8d83e45ec990f45df50f1a286c5fe8bbfb8c6e4246c6389705c0b 0.0s
=> => sha256:c94b82f9827cab6e421b350965a9ef11b25b13ffbd1030536203d541f55dcbe2 2.00kB / 2.00kB 0.0s
=> => sha256:7e9bf114588c05b2df612b083b96582f3b8dbf51647aa6138a50d09d42df2454 17.58MB / 17.58MB 0.7s
=> => sha256:ffd9397e94b74abcb54e514f1430e00f604328d1f895eadbd482f08cc02444e5 51.89MB / 51.89MB 1.3s
=> => sha256:f77a1aef2da8d83e45ec990f45df50f1a286c5fe8bbfb8c6e4246c6389705c0b 776B / 776B 0.0s
=> => sha256:1ddc7e4055fdb6f6bf31063b593befda814294f9f904b6ddfc21ab1513bafa8e 7.23kB / 7.23kB 0.0s
=> => sha256:311da6c465ea1576925360eba391bcd32dece9be95960a0bc9ffcb25fe712017 50.50MB / 50.50MB 0.8s
=> => sha256:513d779256048c961239af5f500589330546b072775217272e19ffae1635e98e 191.90MB / 191.90MB 3.0s
=> => sha256:ae3b95bbaa61ce24cefdd89e7c74d6fbd7713b2bcae93af47063d06bd7e02172 4.20kB / 4.20kB 1.1s
=> => extracting sha256:311da6c465ea1576925360eba391bcd32dece9be95960a0bc9ffcb25fe712017 4.2s
=> => sha256:0e421f66aff42bb069dffc26af6d132194b22a1082b08c5ef7cd69c627783c04 34.79MB / 34.79MB 1.9s
=> => sha256:ca266fd6192108b67fb57b74753a8c4ca5d8bd458baae3d4df7ce9f42dedcc1d 2.27MB / 2.27MB 1.6s
=> => sha256:ee7d78be1eb92caf6ae84fc3af736b23eca018d5dedc967ae5bdee6d7082403b 450B / 450B 1.9s
=> => extracting sha256:7e9bf114588c05b2df612b083b96582f3b8dbf51647aa6138a50d09d42df2454 0.6s
=> => extracting sha256:ffd9397e94b74abcb54e514f1430e00f604328d1f895eadbd482f08cc02444e5 3.3s
=> => extracting sha256:513d779256048c961239af5f500589330546b072775217272e19ffae1635e98e 9.5s
=> => extracting sha256:ae3b95bbaa61ce24cefdd89e7c74d6fbd7713b2bcae93af47063d06bd7e02172 0.0s
=> => extracting sha256:0e421f66aff42bb069dffc26af6d132194b22a1082b08c5ef7cd69c627783c04 1.8s
=> => extracting sha256:ca266fd6192108b67fb57b74753a8c4ca5d8bd458baae3d4df7ce9f42dedcc1d 0.1s
=> => extracting sha256:ee7d78be1eb92caf6ae84fc3af736b23eca018d5dedc967ae5bdee6d7082403b 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 387B 0.0s
=> [2/4] WORKDIR /app 0.4s
=> [3/4] COPY . . 0.1s
=> [4/4] RUN npm install express 3.9s
=> exporting to image 0.2s
=> => exporting layers 0.1s
=> => writing image sha256:ce32f52d37a96926729f2c4fc3f40bd0d1f24bf1efe9ded7348b9681a2933876 0.0s
=> => naming to docker.io/library/my-backend 0.0s
ビルドできたら作成されたイメージを確認します。
my-backend イメージが作成されているかと思います。
[root@con-test ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-backend latest ce32f52d37a9 53 seconds ago 916MB
my-frontend latest 0ddf02aa6138 6 hours ago 52.5MB
作成した my-backend イメージから backend コンテナを起動していきます。
「--network my-network」で先程作成した my-network という名前の Docker ネットワークにこのコンテナを接続するように指定しています。
[root@con-test ~]# docker run -d --name backend --network my-network my-backend
7dbdb9b75c6232a0aca36a6d3afcb412d91207869ffc07b3498a0d9a88776e38
backend コンテナが作成された事を確認します。
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7dbdb9b75c62 my-backend "docker-entrypoint.s…" 7 seconds ago Up 5 seconds backend
b9ab79e88f2b my-frontend "/docker-entrypoint.…" 6 hours ago Up 6 hours 0.0.0.0:80->80/tcp frontend
フロントエンドコンテナ再作成
フロントエンドからバックエンドにリクエストを向かせたいので
フロントエンドの nginx.conf と index.html を更新して再度ビルドします。
フロントエンドからバックエンドへの通信を行うため、バックエンドコンテナへのリバースプロキシを設定します。
nginx.conf を作成します。
[root@con-test ~]# vim /root/frontend/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
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;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
server {
listen 80; # HTTPリクエストをポート80で受け付け
# 静的ファイルの提供設定
location / {
root /usr/share/nginx/html;
index index.html;
}
# APIリクエストのリバースプロキシ設定
location /api/ {
proxy_pass http://backend:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
「proxy_pass http://backend:3000/;」
こちらでバックエンドコンテナにリクエストが向くように指定しています、コピペでOKです。
続いて index.html
[root@con-test ~]# vim /root/frontend/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Frontend</title>
</head>
<body>
<h1>Frontend is running!</h1>
<p>Data from backend: <span id="data"></span></p>
<script>
fetch('http://3.112.126.88:3000/api/data')
.then(response => response.json())
.then(data => document.getElementById('data').innerText = data.message)
.catch(error => console.error('Error fetching data:', error));
</script>
</body>
</html>
「fetch('http://3.112.126.88:3000/api/data')」
IPアドレスはEC2のパブリックIPです。
この行で、fetchを使い指定したURLにGETリクエストを送信させています。
こちらもIPアドレス以外コピペでOKです。
作成した nginx.conf をバックエンドコンテナにコピーさせたいので Dockerfile も更新します。
[root@con-test ~]# vim /root/frontend/Dockerfile
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY index.html /usr/share/nginx/html/
nginx.conf, index.html の更新反映のため再度フロントエンドのイメージをビルドします。
[root@con-test ~]# docker build -t my-frontend /root/frontend/
[+] Building 1.6s (8/8) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 132B 0.0s
=> [internal] load metadata for docker.io/library/nginx:alpine 1.3s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [1/3] FROM docker.io/library/nginx:alpine@sha256:41523187cf7d7a2f2677a80609d9caa14388bf5c1fbca9c410ba3de602aaaab4 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 1.37kB 0.0s
=> [2/3] COPY nginx.conf /etc/nginx/nginx.conf 0.0s
=> [3/3] COPY index.html /usr/share/nginx/html/ 0.1s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => writing image sha256:4dc2a9145221ed76743443f994a0e294d89484bfe673aa606cbb99629c9c1e16 0.0s
=> => naming to docker.io/library/my-frontend 0.0s
ビルドが完了したら、
新規にフロントエンドコンテナを作成するため、現在のフロントエンドコンテナを削除します。
docker stop コマンドでコンテナを停止、
docker rm コマンドでコンテナを削除する事ができます。
フロントエンドコンテナ削除前
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7dbdb9b75c62 my-backend "docker-entrypoint.s…" 7 seconds ago Up 5 seconds backend
b9ab79e88f2b my-frontend "/docker-entrypoint.…" 6 hours ago Up 6 hours 0.0.0.0:80->80/tcp frontend
frontend コンテナを削除していきます。
[root@con-test ~]# docker stop frontend
frontend
[root@con-test ~]# docker rm frontend
frontend
フロントエンドコンテナが削除された事を確認します。
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7dbdb9b75c62 my-backend "docker-entrypoint.s…" 3 minutes ago Up 3 minutes backend
frontend コンテナが削除されている事を確認できました。
更新した Docker イメージからフロントエンドコンテナを起動させます。
frontend コンテナも my-network に接続させます。
[root@con-test ~]# docker run -d --name frontend --network my-network -p 80:80 my-frontend
85082f66015b375ffb68550e4e656269451ec8185988abc96ff39de2513de1ce
フロントエンドコンテナの起動を確認します。
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85082f66015b my-frontend "/docker-entrypoint.…" 6 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp frontend
7dbdb9b75c62 my-backend "docker-entrypoint.s…" 5 minutes ago Up 5 minutes backend
frontend コンテナの STATUS が Up となっているので無事起動しています。
フロントエンド→バックエンドの通信が通るか動作確認を行います。
まず docker exec コマンドを使用して frontend コンテナに接続します。
[root@con-test ~]# docker exec -it frontend sh
/ #
次に frontend コンテナから backend コンテナに curl コマンドを叩いてみます。
/ # curl http://backend:3000/api/data
{"message":"Hello from Backend!"}/ #
「"Hello from Backend!"」が確認できたらOKです。
フロントエンド→バックエンドの接続が確認できたので、最後にDBコンテナを作成していきます。
DBコンテナ作成
DBコンテナ用にディレクトリを用意していきます。
[root@con-test ~]# mkdir /root/db
DB用の初期化スクリプト作成します。
このスクリプトを使用することで、MySQLのデータベースとテーブルの初期設定を自動化できます。
[root@con-test ~]# vim /root/db/init.sql
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE messages (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255));
INSERT INTO messages (message) VALUES ('Hello from MySQL!');
「CREATE DATABASE testdb;」
testdb というデータベースを作成しています。
「USE testdb;」
作成した testdb に接続しています。
「CREATE TABLE messages (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255));」
messages という名前のテーブルを作成して
「INSERT INTO messages (message) VALUES ('Hello from MySQL!');
テーブル messages に、"Hello from MySQL!" というメッセージを持つ1行のデータを挿入しています。
これでテスト用のデータベースとテーブルを用意されるようになります。
DBコンテナ用に Dockerfile を作成します。
[root@con-test ~]# vim /root/db/Dockerfile
FROM mysql:8
ENV MYSQL_ROOT_PASSWORD=password
COPY init.sql /docker-entrypoint-initdb.d/
「FROM mysql:8」
MySQL 8 をベースにした公式イメージを使用します。
「ENV MYSQL_ROOT_PASSWORD=password」
root用のパスワードに password を指定しています。
「COPY init.sql /docker-entrypoint-initdb.d/」
先程作成した init.sql をDBコンテナにコピーします。
DB用の Dockerfile が用意できたのでビルドしていきます。
[root@con-test ~]# docker build -t my-mysql /root/db
[+] Building 16.0s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 126B 0.0s
=> [internal] load metadata for docker.io/library/mysql:8 1.9s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 215B 0.0s
=> [1/2] FROM docker.io/library/mysql:8@sha256:106d5197fd8e4892980469ad42eb20f7a336bd81509aae4ee175d852f5cc4565 13.6s
=> => resolve docker.io/library/mysql:8@sha256:106d5197fd8e4892980469ad42eb20f7a336bd81509aae4ee175d852f5cc4565 0.0s
=> => sha256:6f5cca38a221c35a53694cce3b34887a1cf73335b1c53075114a140a99de0b93 885B / 885B 0.4s
=> => sha256:1ecf42d360987627bcf76572ba479f3b5b0a5391a125801617909cc56e7cb22e 2.85kB / 2.85kB 0.0s
=> => sha256:3818a28b4a67a9efab3547df8a292de847636d5903f7705d4ccbe1d281b20133 6.48kB / 6.48kB 0.0s
=> => sha256:d7c84b66ede077e0a8717528112591fbfd5f3ced4040c124eb6659b3c14940d4 983.00kB / 983.00kB 0.2s
=> => sha256:106d5197fd8e4892980469ad42eb20f7a336bd81509aae4ee175d852f5cc4565 2.60kB / 2.60kB 0.0s
=> => sha256:2c0a233485c3a7b6cab556a9a9c2916ca9a3afc8c46097ddfbe0af4fe120a50c 49.10MB / 49.10MB 1.0s
=> => sha256:299f6f88c6cfd0fdcd8f375f1c26bdd1d4f04eded1587b11419b7f8ae0934d3b 6.90MB / 6.90MB 0.6s
=> => sha256:d39eae8f992719502e3a1d7552504b1acad7bf67f068af86e0dec581ddad018f 2.61kB / 2.61kB 0.6s
=> => sha256:ec0557361569a8ecbc29bb910b4bde5cdaad19c06a71ae771a273afa01543d28 334B / 334B 0.8s
=> => sha256:f6d0f80cb1bedb26d1fbd402a1b7788789ef10b76310425c826d463cdcc034e9 47.56MB / 47.56MB 1.4s
=> => sha256:d496030b710c9fcd2314de6c4b1e7921739e9552cf0338ebd4b51de517252e01 321B / 321B 1.1s
=> => sha256:4d755d8c89d19d65a71254593f2410f5bc54a1b5cb51b4763665bbfd08f05451 66.96MB / 66.96MB 2.1s
=> => extracting sha256:2c0a233485c3a7b6cab556a9a9c2916ca9a3afc8c46097ddfbe0af4fe120a50c 2.5s
=> => sha256:699d8e3dc44b682de3b43954ad50435abff0302f59f790cbe032bb70f7edc214 5.33kB / 5.33kB 1.3s
=> => extracting sha256:6f5cca38a221c35a53694cce3b34887a1cf73335b1c53075114a140a99de0b93 0.0s
=> => extracting sha256:d7c84b66ede077e0a8717528112591fbfd5f3ced4040c124eb6659b3c14940d4 0.0s
=> => extracting sha256:299f6f88c6cfd0fdcd8f375f1c26bdd1d4f04eded1587b11419b7f8ae0934d3b 0.3s
=> => extracting sha256:d39eae8f992719502e3a1d7552504b1acad7bf67f068af86e0dec581ddad018f 0.0s
=> => extracting sha256:ec0557361569a8ecbc29bb910b4bde5cdaad19c06a71ae771a273afa01543d28 0.0s
=> => extracting sha256:f6d0f80cb1bedb26d1fbd402a1b7788789ef10b76310425c826d463cdcc034e9 1.5s
=> => extracting sha256:d496030b710c9fcd2314de6c4b1e7921739e9552cf0338ebd4b51de517252e01 0.0s
=> => extracting sha256:4d755d8c89d19d65a71254593f2410f5bc54a1b5cb51b4763665bbfd08f05451 7.5s
=> => extracting sha256:699d8e3dc44b682de3b43954ad50435abff0302f59f790cbe032bb70f7edc214 0.0s
=> [2/2] COPY init.sql /docker-entrypoint-initdb.d/ 0.4s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:7a8ebfb14f601a08fe2a2c2a0f385709b33edc078a1c354c6e3eb895d01cef0c 0.0s
=> => naming to docker.io/library/my-mysql 0.0s
作成されたイメージを確認します。
[root@con-test ~]# docker images my-mysql
REPOSITORY TAG IMAGE ID CREATED SIZE
my-mysql latest 7a8ebfb14f60 About a minute ago 594MB
イメージの作成が確認できたのでDBコンテナを作成していきます。
DBコンテナも my-network に接続させます。
これにより、フロントエンド、バックエンド、DBコンテナが全て同じネットワーク構成になります。
[root@con-test ~]# docker run -d --name db --network my-network -e MYSQL_ROOT_PASSWORD=password my-mysql
10e31206c40fade9b1cd4c43c68108b036a23002fc4a0b6473cab7657793c473
DBコンテナが作成された事を確認します。
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10e31206c40f my-mysql "docker-entrypoint.s…" 12 seconds ago Up 11 seconds 3306/tcp, 33060/tcp db
e9e426feb80f my-backend "docker-entrypoint.s…" 17 minutes ago Up 17 minutes backend
85082f66015b my-frontend "/docker-entrypoint.…" 32 minutes ago Up 32 minutes 0.0.0.0:80->80/tcp frontend
折角なので作成したDBコンテナに入ってみます。
[root@con-test ~]# docker exec -it db mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.4.3 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
testdb の作成を確認して
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
+--------------------+
5 rows in set (0.01 sec
testdb に接続します。
mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
テスト用の messages テーブルが作成されている事を確認し
mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| messages |
+------------------+
1 row in set (0.00 sec)
messages テーブルの中身も見てみます。
mysql> select * from messages;
+----+-------------------+
| id | message |
+----+-------------------+
| 1 | Hello from MySQL! |
+----+-------------------+
1 row in set (0.00 sec)
「Hello from MySQL!」が確認できたらOKです。
確認できたら「Ctrl+D」で抜けます。
バックエンドコンテナ再作成
バックエンドからDBに接続させるため、バックエンドの app.js と Dockerfile を編集します。
バックエンド更新 app.js
[root@con-test ~]# vim /root/backend/app.js
const express = require('express');
const mysql = require('mysql2');
const cors = require('cors');
const app = express();
// CORSを許可
app.use(cors());
const db = mysql.createConnection({
host: 'db',
user: 'root',
password: 'password',
database: 'testdb',
waitForConnections: true,
connectionLimit: 10, // 最大接続数
queueLimit: 0
});
// データ取得用のAPIエンドポイント
app.get('/api/data', (req, res) => {
db.query('SELECT message FROM messages LIMIT 1', (err, results) => {
if (err) {
console.error('Database query failed:', err);
res.status(500).send('Database query failed');
return;
}
res.json({ message: results[0].message });
});
});
// サーバーを起動
app.listen(3000, () => {});
「app.use(cors());」
CORSエラーを防ぐため追加しています。
「const db = mysql.createConnection({ ~」
こちらでデータベースコンテナのホスト名やユーザ名など指定しています。
「app.get('/api/data', (req, res) => { ~」
こちらで /api/data にリクエストが来た際にDBコンテナから値を取得するようにしています。
詳細割愛させてもらえればと思います、コピペでOKです。
バックエンド用の Dockerfile を編集します。
[root@con-test ~]#vim /root/backend/Dockerfile
FROM node:16
WORKDIR /app
COPY . .
RUN npm install express mysql2 cors
RUN apt-get update && apt-get install -y default-mysql-client
CMD ["node", "app.js"]
mysql2,cors ライブラリを追加して、MySQLクライアントツールをインストールするように更新しています。
ファイルを更新できたのでバックエンドの再ビルドを行います。
[root@con-test ~]# docker build -t my-backend /root/backend/
[+] Building 14.1s (10/10) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 196B 0.0s
=> [internal] load metadata for docker.io/library/node:16 1.1s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/5] FROM docker.io/library/node:16@sha256:f77a1aef2da8d83e45ec990f45df50f1a286c5fe8bbfb8c6e4246c6389705c0b 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 1.05kB 0.0s
=> CACHED [2/5] WORKDIR /app 0.0s
=> [3/5] COPY . . 0.0s
=> [4/5] RUN npm install express mysql2 cors 4.4s
=> [5/5] RUN apt-get update && apt-get install -y default-mysql-client 7.8s
=> exporting to image 0.6s
=> => exporting layers 0.5s
=> => writing image sha256:14250946b34e7de953912c7eea2edd497b16f124053c1b04335a8c58b8c2c511 0.0s
=> => naming to docker.io/library/my-backend 0.0s
バックエンドコンテナの再作成を行うため、起動中のバックエンドコンテナを削除します。
[root@con-test ~]# docker stop backend
backend
[root@con-test ~]# docker rm backend
backend
バックエンドコンテナの削除を確認します。
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10e31206c40f my-mysql "docker-entrypoint.s…" 15 minutes ago Up 15 minutes 3306/tcp, 33060/tcp db
85082f66015b my-frontend "/docker-entrypoint.…" 47 minutes ago Up 47 minutes 0.0.0.0:80->80/tcp frontend
バックエンドコンテナを起動させます。
[root@con-test ~]# docker run -d --name backend --network my-network -p 3000:3000 my-backend
cf4b68392045963b8f339d15ef8d068df7acfb7fe099eed2fddfee7e0bc00f3f
これで、フロントエンド、バックエンド、DBコンテナが起動されている状態になりました。
[root@con-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf4b68392045 my-backend "docker-entrypoint.s…" 32 seconds ago Up 32 seconds backend
10e31206c40f my-mysql "docker-entrypoint.s…" 19 minutes ago Up 19 minutes 3306/tcp, 33060/tcp db
85082f66015b my-frontend "/docker-entrypoint.…" 50 minutes ago Up 50 minutes 0.0.0.0:80->80/tcp frontend
動作確認
サーバ上でフロントエンド→バックエンド→DBで接続できるか試してみます。
フロントエンド→バックエンド
フロントエンドに接続して
[root@con-test ~]# docker exec -it frontend sh
/ #
バックエンドに対して curl コマンドを叩きます。
/ # curl http://backend:3000/api/data
{"message":"Hello from MySQL!"}/ #
この時点で Hello from MySQL! が表示されてますが念のためバックエンド→DBも試していきます。
「Ctrl+D」で抜けます。
バックエンド→DB
バックエンドに接続して
[root@con-test ~]# docker exec -it backend bash
root@cf4b68392045:/app#
mysqlにログインします。
root@cf4b68392045:/app# mysql -h db -uroot -ppassword
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.4.3 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
無事接続確認できました、「Ctrl+D」で抜けます。
最後に、ブラウザ上からフロントエンド→バックエンド→DBコンテナの連携を確認します。
ブラウザで http://<EC2のパブリックIP> にアクセスし、「Data from backend: Hello from MySQL!」が表示されれば成功です。
お疲れ様でした。
以上で、フロントエンド→バックエンド→DBコンテナを連携させる事ができました。
今回は、実際にコンテナを作成したり削除する事でコンテナが構成される流れや
コンテナならではの「起動の速さ」や「軽量で扱いやすい特長」を体感することができました。
この記事がエンジニア初学者の参考になれば幸いです。
ここまでお付き合いいただき、誠にありがとうございました。
引き続き、アドベントカレンダーをお楽しみください。