Dockerによるコンテナ化入門ガイド
この記事は弊社のフルスタックエンジニア:Ashish Dhakalが作成した記事です。英語版はこちらをご覧ください。
Medium
ソフトウェアを開発する際、異なるマシン間で一貫した環境を維持することは難しいことです。Dockerは、アプリケーションとその依存関係を軽量でポータブルなコンテナにパッケージ化することで、この問題を解決する強力なツールです。このガイドでは、DockerとDocker Composeの初心者向けに、MySQLデータベースに接続したNode.jsアプリケーションをDocker Composeを使ってコンテナ化し、マルチコンテナオーケストレーションする方法を説明します。
ドッカーとは?
Dockerは、コンテナと呼ばれる隔離された環境内でアプリケーションをビルド、デプロイ、実行できるプラットフォームです。コンテナは、アプリケーション、その依存関係、ライブラリ、設定ファイルなど、実行環境全体をバンドルします。これにより、アプリケーションは、開発マシンであろうと本番サーバーであろうと、どこにデプロイされても同じように実行されます。
Dockerを使う主なメリット
異なるステージ(開発、テスト、本番)で一貫した環境を実現。
サービスの分離により、デバッグが容易になります。
従来の仮想マシンよりも軽量で高速。
Docker Composeとは?
Docker Composeは、複数のDockerコンテナを単一のアプリケーションの一部として定義・管理するツールです。docker-compose.ymlファイルを使用して、アプリケーションが必要とするすべてのサービス(Webサーバ、データベースなど)を指定し、docker-compose upというコマンド1つで実行できるようにします。
Docker Composeの主な利点:
マルチコンテナアプリケーションの管理を簡素化。
.envファイルによる環境設定をサポート。
複雑なマイクロサービスアーキテクチャの定義に便利。
コンテナ化アプリケーションの主な利点
技術的なステップに入る前に、アプリをコンテナ化する理由を簡単に探ってみよう:
一貫性: 環境(開発、ステージング、本番)に関係なく、アプリケーションが同じように実行されることを保証します。
依存関係の管理の簡素化: パッケージと依存関係はコンテナ内にインストールされるため、ホスト環境はクリーンな状態に保たれます。
スケーラビリティとデプロイメント: Kubernetesやクラウドサービスのようなツールを使って、アプリケーションのスケーリングやデプロイが容易になります。
これらの利点を念頭に置いて、NodeJsアプリケーションのコンテナ化のセットアップを始めましょう。
ステップ1:プロジェクト・ディレクトリのセットアップ
まずプロジェクトフォルダを作成し、基本的なNode.jsアプリケーションを初期化します。次に、同じプロジェクトのルート・ディレクトリにDockerfileとdocker-compose.ymlファイルを作成します。
touch Dockerfile docker-compose.yml .env
.envの中に、必要な環境変数をすべて追加する:
PORT=8090
DB_HOST=db
DB_USER=root
DB_PASSWORD=password
DB_NAME=todo_db
DB_PORT=3306
ADMINER_PORT=5001
DIALECT=mysql
次に、Dockerfile内に以下の内容を追加する。
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm install -g nodemon
EXPOSE 8090
CMD ["npx", "nodemon", "--watch", ".", "index.js"]
.ymlファイルを分解する
FROM node:16: 使用するベースイメージを指定します。
WORKDIR /app: コンテナ内の作業ディレクトリを設定します。以降のCOPYコマンドやRUNコマンドは、このディレクトリを基準に実行されます。
COPY package*.json ./: package.jsonとpackage-lock.json(ある場合)をコンテナにコピーします。このステップは、ビルドキャッシュを最適化するために別個に行われるため、npmの依存関係が不必要に再インストールされることはない。
npm installを実行する: 1package.jsonで指定された依存関係をすべてインストールする。
COPY ..: すべてのアプリケーションファイルをコンテナ内の/appディレクトリにコピーする。
RUN npm install -g nodemon: 開発中のライブリロードに使用されるnodemonをグローバルにインストールします。
EXPOSE 8090: ポート8090を公開し、アプリケーションへの外部アクセスを許可する。
CMD [「npx」, 「nodemon」, 「 - watch」, 「.」, 「index.js」]: コンテナ起動時に実行するコマンドを設定します。ここでは、nodemonがコードの変更を監視し、サーバを自動的に再起動します。
このDockerfileをセットアップした状態で、Docker Composeを使ってこのイメージを実行してみよう。
ステップ2:docker-compose.ymlファイルのセットアップ
コンテナは1つでも便利ですが、実際のアプリケーションでは複数のサービス(データベースなど)が必要になることがほとんどです。Docker Composeを使えば、マルチコンテナ・アプリケーションを定義・管理できる。この例では、以下を含むdocker-compose.ymlファイルを設定します:
Node.jsアプリケーションサービス
MySQLデータベースサービス
Adminer(データベース管理ツール)
docker-comppose.ymlに以下のコードを追加する。
version: '3.8'
services:
# Node.js Application Service
app:
build:
context: .
dockerfile: Dockerfile
container_name: nodejs-app
restart: always
ports:
- ${PORT}:${PORT} # Map host port {PORT} to container port {PORT} for the Node.js server
environment:
DB_HOST: db
DB_USER: root
DB_PASSWORD: password
DB_NAME: todo_db
volumes:
- .:/app # Mount the current directory to the container for hot-reload
- /app/node_modules
depends_on:
- db
# MySQL Database Service
db:
image: mysql:8.0
container_name: mysql-db
restart: always
environment:
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
ports:
- ${DB_PORT}:${DB_PORT} # Map host port {DB_PORT} to container port 3306
volumes:
- db_data:/var/lib/mysql
# Adminer Service for DB Management
adminer:
image: adminer
container_name: adminer
restart: always
ports:
- ${ADMINER_PORT}:8080 # Map host port {ADMINER_PORT} to Adminer’s internal port 8080
depends_on:
- db
# Define Volumes for Persistent Data Storage
volumes:
db_data:
.ymlファイルを分解しよう
├── Version: We specify version 3.8 to use the latest features of Docker Compose.
├── Services: We defined 3 different services, `app`, `db`, `adminer`
│ └── app:
│ │ └── Uses the Dockerfile to build the image.
│ │ └── Sets environment variables for database connection.
│ │ └── Maps the current directory (.) to the /app directory inside the container, enabling hot-reloading.
│ └── db: Configures the MySQL database:
│ │ └── Uses the mysql:8.0 image.
│ │ └── Sets up environment variables for the database credentials and name.
│ │ └── Maps port 3306 for accessing the database.
│ └── adminer: Sets up Adminer:
│ │ └── Uses the adminer image.
│ │ └── Maps port 5001 for easy access to the database management interface.
└── Volumes: Volumes
└── db_data: Defines a db_data volume for persistent MySQL storage.
ステップ3:コンテナのビルドと実行
Dockerfileとdocker-compose.ymlの準備ができたので、コンテナをビルドして実行してみよう。
Dockerイメージをビルドする
Dockerfileとdocker-compose.ymlがあるディレクトリに移動し、実行する:
docker-compose build
このコマンドは、docker-compose.ymlで定義されたイメージをビルドします。
Dockerコンテナの実行
docker-composeファイルで定義されたすべてのサービスを起動するには、次のコマンドを使用します:
docker-compose up
このコマンドは、Node.jsアプリ、MySQLデータベース、Adminerをスピンアップします。アクセスできます:
Node.js アプリ: http://localhost:8090
Adminer: http://localhost:5001
コンテナの停止
サービスを停止したい場合は、次のコマンドを使用する:
docker-compose down
これで、すべてのコンテナが潔く停止する。
結論
Dockerを使用してNode.jsアプリケーションをコンテナ化し、Docker Composeで管理することで、一貫した環境を維持し、複数のサービスを扱い、デプロイを効率化する簡単な方法を提供します。
Happy coding! 🎉