Docker で Express アプリをデプロイする(http) - AlmaLinux

  • 作成日:
  • 最終更新日:2025/06/25

デプロイ環境

ホスト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
    • express-app
      • Dockerfile
      • Express-generator で作成したファイル
    • docker-compose.yml

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 のページが表示されれば設定完了です。