Dockerについてわかりやすくまとめてみました
Dockerとは
Dockerは、アプリケーションやサービスを環境から切り離して実行できるコンテナと呼ばれる軽量で独立した環境を利用して、アプリケーションの開発、配信、実行を簡素化するためのツールです。
Docker Desktopのインストール
下記を参考にOS上でDocker環境が使えるようにしてください。
コンテナ(Container)
Dockerコンテナは、Dockerイメージから作成されるアプリケーションやサービスを実行するための独立した実行環境です。
イメージ(Image)
Dockerイメージは、コンテナを作成するための静的なファイルのセットです。これには、実行に必要なすべてのファイル、データ、および設定が含まれており、Dockerfile
と呼ばれるテキストファイルを使用して定義されています。
また、イメージはDocker HubなどのDockerレジストリで共有して再利用することができます。
ボリューム(Volume)
Dockerボリュームは、Dockerコンテナにデータを永続化するための手段で、コンテナが停止または削除されてもデータが保持されます。
複数のウェブサーバーコンテナが同じボリュームを使用してデータにアクセスできるため、異なるコンテナ間でデータを共有することが可能です。
Dockerfile
コンテナイメージを管理するためのファイルで、ベースイメージの指定、必要なパッケージのインストール、ファイルのコピー、環境変数の設定など、イメージを構築するための手順が記述されています。
# ベースイメージの選択
FROM node:18
# アプリケーションディレクトリを作成
# docker-compose.ymlのvolumesと同じパスにする
WORKDIR /app
# アプリケーションの依存ファイルをインストール
COPY package*.json ./
# 依存関係のインストール
RUN npm install
# アプリケーションのソースコードをコピー
COPY . .
# ポート3000を公開
EXPOSE 3000
# アプリケーションの起動
CMD ["npm", "run", "dev"]
RUN
Dockerイメージをビルドする過程で実行されるコマンドです。
主にソフトウェアのインストールや設定ファイルの編集など、イメージの構築に必要な手順を実行するために使用されます。RUN
コマンドで実行された結果は、その時点でのイメージの一部として保存されます。
WORKDIR
Dockerコンテナ内での作業ディレクトリを設定
ENTRYPOINT
コンテナが起動する際に実行されるコマンドを設定
CMD
コンテナが実行された際にデフォルトで実行されるコマンドを指定
コンテナのデフォルトの実行コマンドを設定するために用いられ、Dockerfile内に一つだけ存在することができます。もし複数のCMD
コマンドがある場合は、最後のCMD
コマンドが有効になります。
docker-compose.yml
Docker Compose(docker-compose.yml
)は、複数のDockerコンテナを定義し、管理するためのツールです。
このファイルでは、各サービスのイメージ、ポートマッピング、環境変数、ボリュームのマウントなど、コンテナの構成を定義しています。docker-compose
コマンドを使用して、このファイルを読み込み、複数のコンテナを一度に起動、停止、管理することができます。
version: '3.8'
services:
app:
container_name: app
build: .
volumes:
- .:/app
ports:
- '3000:3000'
env_file:
- .env
depends_on:
- db
platform: linux/amd64
networks:
- app-network
db:
image: mysql:8.0
ports:
- '3306:3306'
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=test_db
volumes:
- db-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
platform: linux/amd64
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
db-data:
version
ファイルの先頭で指定される部分であり、使用しているDocker Compose
のファイルフォーマットのバージョンを示しています。
container_name
コンテナの名前を指定する
version
Docker Composeファイルのバージョンを指定します。
services
Docker Composeが管理する各サービス(コンテナ)が定義されます。
今回は、2つのコンテナ(app
とdb
)を定義しています。
build
Dockerfileの場所を指定しています。
volumes
今回の.:/app
という記述では、ホストマシンの現在のディレクトリ(.
)をコンテナ内の/app
ディレクトリにマウントしています。
この設定により、ホストマシン上とコンテナ内の/app
ディレクトリの間でファイルの同期が行われるので、ホストマシン上のエディタでコードを編集した際にその変更をコンテナ内のアプリケーションに即座に反映することができます。
ports
ホストとコンテナのポートのマッピングを指定しています。
今回は、ホストマシンのポート3000とコンテナ内のポート3000をマッピングしており、ホストマシンのポート3000にリクエストが送信されると、そのリクエストはDockerコンテナ内のポート3000に転送されます。
env_file
環境変数ファイルを指定しています。
environment
環境変数を設定しています。
depends_on
db
コンテナが起動してからapp`サービスが起動するように制御してます。
image
使用するDockerイメージを指定します。
今回は、MySQLの公式イメージmysql:5.7
を使用しています。
platform
コンテナが実行されるプラットフォームを指定しています。
今回は、M1 Macを使用しているためlinux/amd64
と記述しています。
networks
コンテナ間で通信するためのネットワークを定義しています。複数のコンテナが同じネットワークに接続されると、それらのコンテナ間で通信することができます。
今回は、app-network
という名前のネットワークを定義しており、app
コンテナとdb
コンテナが同じapp-network
ネットワークに接続されているため、2つのコンテナは相互に通信することができます。
volumes
db-data:/var/lib/mysql
では、データベースのデータを永続化するためのボリュームを設定しています。
今回は、db-data
という名前のボリュームを定義し、MySQLデータベースのデータがDockerボリュームに保存されるようにしています。
./init.sql:/docker-entrypoint-initdb.d/init.sql
では、、初期化用のSQLファイルをマウントします。
restart: unless-stopped
コンテナが異常終了した場合に自動的に再起動されるように設定できます。ただし、手動で停止した場合は再起動されません。
データベースの初期化スクリプトの追加
init.sql
ファイルをdocker-compose.yml
にパスを指定することで、Dockerコンテナが起動する際にinit.sql
ファイルが自動的に実行され、データベースのセットアップが行われています。
プロジェクトのルートディレクトリに移動してinit.sql
ファイルを作成してください。
touch init.sql
init.sql
の内容は次のようにします。
SET CHARSET UTF8;
CREATE DATABASE IF NOT EXISTS test_db;
USE test_db;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
INSERT INTO users (first_name, last_name) VALUES ('山田', '太郎'), ('山田', '花子');
MySQLデータベースに対して以下の操作を行っています。
SET CHARSET UTF8;
文字セットをUTF-8に変更することで、データベースが日本語のテキストを正しく扱えるようになります。
CREATE DATABASE IF NOT EXISTS test_db;
データベースが存在しない場合は、test_db
という名前のデータベースを作成します。test_db
のデータベースがすでに存在する場合は何もしません。
USE test_db;
以降の操作を実行するデータベースを選択しています。
CREATE TABLE IF NOT EXISTS users (...)
users
という名前のテーブルが存在しない場合は、新しいテーブルを作成します。
INSERT INTO users (first_name, last_name) VALUES ('山田', '太郎'), ('山田', '花子');
users
テーブルに新しいデータを挿入しています。
コマンド
Dockerイメージをビルド
Dockerは以前のビルドから生成されたキャッシュを使用してイメージをビルドします。このキャッシュ利用により、ビルドプロセスが速くなります。
例えば、Dockerfile のある命令が変更されていない場合、その命令の実行結果がキャッシュされていれば、再び実行する代わりにキャッシュから結果を取得し、時間とリソースの節約につながります。
docker-compose build
build
セクション(Dockerfile
やベースイメージ)に設定変更があった場合には、再ビルドが必要です。
--no-cache
Dockerは一切のキャッシュを使用せずにイメージをビルドします。これにより、すべての命令がゼロから実行されるため、最新の状態で完全に新しいイメージを保証できます。
コンテナを起動
docker-compose.yml
ファイルに基づいてサービスを起動しています。
docker-compose up
-d
バックグラウンドでコンテナを起動することができます。
--build
コンテナを起動する前にイメージをビルドします。
コンテナを停止
docker-compose down
ボリュームの一覧を確認
docker volume ls
ボリュームの削除
docker volume rm <ボリューム名>
Dockerコンテナの中に入る
docker exec -it <コンテナID> /bin/bash
/bin/
のパスは省略することができるので、下記でも問題ないです。
docker exec -it <コンテナID> bash
コンテナ名を使ってコンテナに入る
docker-compose.yml
ファイルがあるディレクトリに移動してから、
docker compose exec <コンテナ名> bash
Dockerコンテナから出る
exit
MySQLのイメージ
DockerでMySQLイメージを使う際、MYSQL_USER
とMYSQL_PASSWORD
環境変数は通常の(非root)ユーザーを設定するために使います。これらの変数を使ってroot
ユーザーを設定することはできません。
MYSQL_ALLOW_EMPTY_PASSWORD
MySQLユーザー(通常はrootユーザー)がパスワード無しでログインできるかどうかを制御します。
値が1またはyesの場合は、MySQLサーバーのrootユーザーがパスワードなしでログインできるようになります。これにより、特に開発環境での設定やテストが容易になりますが、セキュリティリスクも伴います。
値が0またはnoの場合は、パスワードなしでのログインが不許可となります。この設定は本番環境で推奨されます。
OCI runtime exec failed: exec failed: unable to start container process: exec: "bin/bash": stat bin/bash: no such file or directory: unknown と表示される場合
bin/bash
というパスのファイルが見つからない、または存在しないため実行できないということが示されています。ファイルが存在するか確認してください。
環境変数を変更した場合
コマンドを起動した後に.env
ファイルを追記した場合、その環境変数の変更は反映されません。
コンテナを停止し、再度コンテナを起動すると新しい環境変数が反映されます。
The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8)
Dockerイメージのアーキテクチャがホストシステムのアーキテクチャと一致しないことを示しています。
下記の場合、MySQLのイメージはamd64
プラットフォーム用に作られており、ホストマシンがarm64
アーキテクチャであるため、不一致が起こっています。コンテナが実行されるプラットフォームを指定してください。
version: '3.8'
services:
app:
build: .
volumes:
- .:/app
ports:
- '3000:3000'
env_file:
- .env
depends_on:
- db
platform: linux/amd64 // 追加
networks:
- app-network
db:
image: mysql:8.0
ports:
- '3306:3306'
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=test_db
volumes:
- db-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
platform: linux/amd64 // 追加
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
db-data:
プラットフォームを指定した後、コンテナを再度起動してみてください。
entrypoint.sh
Dockerコンテナが起動する際に最初に実行されるスクリプトです。このスクリプトを使用することで、コンテナ起動時に特定のコマンドやスクリプトを実行することができます。
docker
ディレクトリなどに作成します。
COPY ./docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
#!/bin/sh
php artisan migrate --force
# PHP-FPMを起動
exec "$@"
終わりに
何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉
Discussion