デプロイ環境
ホストOS | AlmaLinux |
ウェブサーバー | Apache |
言語 | Node.js |
フレームワーク | Express.js |
ホストOS(AlmaLinux)は、ローカル上の VirtualBox に構築しています。
Docker のコンテナとして利用するのは、「 Apache、Node.js、Express.js 」をコンテナで利用します。
Docker の設計原則として、「 1つのコンテナには1つのプロセス(または主要な責任)を持たせる 」というものがあります。そのため、ホストOS の「 AlmaLinux 」自体はコンテナで利用しません。
単一責任の原則 (Single Responsibility Principle)
1つのコンテナには1つのプロセス(または主要な責任)を持たせる
Apache、MariaDB をそれぞれ個別のコンテナとして作成し、「 Node.js と Express.js のアプリ 」は、一つのコンテナにまとめます。
プロジェクトのディレクトリ構造
- exapp
- apache
- conf
- httpd-vhosts.conf
- Dockerfile
- conf
- express-app
- Dockerfile
- Express-generator で作成したファイル
- docker-compose.yml
- apache
Apache の設定ファイル
apache/conf/httpd-vhosts.conf
<VirtualHost *:80>
ProxyPass / http://express-app:3000/
ProxyPassReverse / http://express-app:3000/
</VirtualHost>
ファイアウォールの設定を変更するために、以下のコマンドを実行します。
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
docker-compose.yml
version: '3.8'
services:
apache:
build: ./apache
container_name: apache_proxy
ports:
- "80:80"
volumes:
- ./html:/usr/local/apache2/htdocs:z
networks:
- app_network
restart: always
express-app:
build: ./express-app
container_name: express_backend
volumes:
- ./express-app:/usr/src/app:z # コード変更を反映させたい場合
- /usr/src/app/node_modules # node_modules はマウント対象から除外 (ホストのnode_modulesと同期させない)
networks:
- app_network
restart: always
networks:
app_network: # カスタムネットワークを定義
driver: bridge
express-app Dockerfile
# Node.js の公式イメージを使用
FROM node:20-alpine
# 作業ディレクトリを設定
WORKDIR /usr/src/app
# package.json と package-lock.json をコピーして依存関係をインストール
COPY package*.json ./
RUN npm install
# アプリケーションのコード(./express-app ディレクトリ内のほとんどのファイル)は自動でコピーされますが
# .env ファイルは特別で、通常は明示的な設定がないとコンテナにコピーされないためコピーが別途コピーが必要。
COPY conf/.env ./conf/.env
# アプリケーションのコードをコピー
COPY . .
# Express アプリがリッスンするポートを公開
EXPOSE 3000
# アプリケーションを起動
CMD ["npm", "start"]
node:20-alpineの公式イメージを使った場合、コンテナのシェルに入るには以下のコマンドを実行します。
docker exec -it express_backend sh
Alpine Linux は軽量ディストリビューション: alpine というタグが示す通り、このイメージは非常に軽量な Linux ディストリビューションである Alpine Linux をベースにしています。
そのため、bash が含まれていないので sh を利用します。
Docker は、ホストOS カーネルを利用するのに、alpine linux を含めるのは次のような理由のためです。
Dockerコンテナに alpine linux のようなディストリビューションを含めるのは、ホストOSのカーネルとは独立して、アプリケーションを実行するための最小限かつ必要なユーザーランド環境を提供するためです。これにより、コンテナは独立性とポータビリティを保ちつつ、軽量で効率的に動作できます。
alpine linux がない状態だと、Node.jsアプリケーション自体はあっても、それを実行するための node コマンドや依存ライブラリが存在しないため、アプリケーションを起動することすらできない、という状態になってしまいます。
apache Dockerfile
# apache/Dockerfile
FROM httpd:2.4
# Proxy関連、Header、Rewriteモジュールのみを有効化
RUN sed -i '/^#LoadModule proxy_module modules\/mod_proxy.so/s/^#//' /usr/local/apache2/conf/httpd.conf \
&& sed -i '/^#LoadModule proxy_http_module modules\/mod_proxy_http.so/s/^#//' /usr/local/apache2/conf/httpd.conf \
&& sed -i '/^#LoadModule headers_module modules\/mod_headers.so/s/^#//' /usr/local/apache2/conf/httpd.conf \
&& sed -i '/^#LoadModule rewrite_module modules\/mod_rewrite.so/s/^#//' /usr/local/apache2/conf/httpd.conf
# カスタムの httpd-vhosts.conf をコンテナの extra ディレクトリにコピー
COPY ./conf/httpd-vhosts.conf /usr/local/apache2/conf/extra/httpd-vhosts.conf
# デフォルトの httpd.conf に httpd-vhosts.conf をインクルードする設定を追加
# そして、もし httpd-ssl.conf のインクルード行があれば削除
RUN echo "Include conf/extra/httpd-vhosts.conf" >> /usr/local/apache2/conf/httpd.conf \
&& sed -i '/^Include conf\/extra\/httpd-ssl.conf/d' /usr/local/apache2/conf/httpd.conf
# コンテナ起動時にApacheを起動
CMD ["httpd", "-DFOREGROUND"]
Apache の公式イメージに含まれている ディストリビューションは、Debian です。
以下のコマンドを実行し、apache コンテナのシェルに入ります。
docker exec -it apache_proxy bash
シェルに入った後、以下のコマンドを実行し、バージョンが表示されれば、Debian が含まれています。
Debian のディストリビューションのバージョン確認
cat /etc/debian_version
extra ディレクトリは、主に追加的かつモジュールに特化した設定ファイルを整理して格納するための場所です。
コンテナのビルドと起動
Docker イメージをビルドし、コンテナを起動するには次のようにします。
ホストOS ホームディレクトリにプロジェクトのディレクトリをアップロードします。
アップロードが終われば、そのディレクトリに移動して、以下のコマンドを実行します。
docker compose up -d --build
ゲストOS からアクセスしてみます。ブラウザを開き、「 http://サーバーIPアドレス 」でアクセスして Express.js のページが表示されれば設定完了です。