Docker初学者なので色んな環境を作ってみる

Date2026/04/10 Last Modified2026/04/10

そもそもDockerを普段使わない人

xamppで基本的な開発を行っていて、何か別の環境にする必要があったとしても特殊だから、テスト環境を外部で作成して……という風にやっていた。
しかし、色々とやっていくうちにDockerは便利そうだし、あとは制限付きのPCでグローバルにインストールできないツールもDockerで扱えるなどに気付いたとき、そろそろしっかり勉強しないといけないと思って、今日ここに至る。

自分向けなので、かなり大雑把な説明になるのだけれどご愛敬で。

今回やってみたいテーマ

勉強がてら、以下の環境を作ってみる。車輪を再発明。

  • Mailpitでメールサーバーを立ち上げて送信する

まずはDockerを知る

この先の説明は先人たちが無限にしてきていることだと思うけれど、自分でもあえて書いてみる。

Docker Desktopを立ち上げると、以下のようになっている。

  • containers
  • images
  • volumes
  • builds

まずcontainersは、AWSで例えるとEC2インスタンスのようなものだと思えば良い。
これを起動すればサーバーが動くし、停止すればサーバーが止まるが、消えるわけではないということ。
次にimagesは、AMIのようなもの。インスタンスの設計図にあたるもので、このimagesをもとにcontainersを生成することができる。また、containerはimageを参照し続けるので、imageを消そうとしても参照されている場合は消せない。
volumesは、データベースになる。xamppの環境に比べて便利なのは、データベースのバージョンをcontainerごとに変えられるという点。Dockerを使う=異なる様々な実行環境を用意するということなので、volumeも個々で独立して作成できる。(なお並列して置くことも可能ではある)
buildsは、ビルド履歴を管理する場所であり過程を示すもの。なおビルドとは、Dockerfileからimageを作る工程である。そのため、同じビルドを行うときはキャッシュで安定かつ高速に実現することができる。あんまり気にする必要はなさそうに思う。

ということで、全体像がつかめたので
「なんでimageを消そうとしてもエラーが出るんだよ!!」というのは無くなりそう。

Dockerの起動から流れをつかむ

Dockerの構築にあたって、用意すべきファイル群と、各種コマンドがどういう動きをしているのかを具体的に観察してみる。

必ず使うファイル

  • Dockerfile
  • docker-compose.yaml

Dockerfileはイメージの作成手順書であり、いわばレシピ。
ここで押さえておきたいのが「なぜこのDockerfileが必要なのか?」ということである。
例えば、phpのバージョンだけを変えたいとなった場合はphp:8.2-cliを土台にdocker環境を作るのだが、OSの違いを再現したいときはubuntu:22.04を土台にして、ubuntuでRUN apt-get update && \ apt-get install -y php php-cliを実行するといった形になる。
どれだけ今の環境から離れているのか、というのを書くのがDockerfileである。
なので、まったく同じでいいならxamppを使えば良いんだなあと思っておく。

docker-compose.yamlは、複数のコンテナを管理するためのファイル。
どういったcontainerを作成したいかをyamlファイルに定義していくのだが、言ってみると部品を列挙していく感じ。
各部品は「image」であり、このimageはクラウドにあるイメージを使用するか、Dockerfileからビルドして作成するかに分かれる。
dockerの考え方ではOSは基盤というより、これもまた部品である。
そのため、もしもクラウドにあるimageだけで構成できるのならばdockerfileはいらないし、いくつもの部品でオリジナルなものが必要であればdockerfileを複数置いてyamlに定義するのである。

Mailpitを入れてみよう

これらの前提を踏まえた上で、Mailpitを使ってDocker環境からメールを送受信してみる。
まずはMailpitを構成するためのdocker-compose.ymlを用意する。

services:
  mailpit:
    image: axllent/mailpit:latest
    container_name: mailpit
    ports:
      - "1025:1025"
      - "8025:8025"
$ docker compose up -d
http://localhost:8025

これでMailpitの画面が表示される。

ここで一つの疑問があり、「なぜMailpitをダウンロードしただけなのに、管理画面があるんだろう?」という点である。
私のイメージとしては、「Mailpit=メールサーバー」であり、なぜ管理画面も提供されているのか、htmlファイルもあるのか……?という疑問が出てきた。   このyamlファイルを置いたフォルダを起点にアプリケーションを起動しているはずなのに、このアプリ内にない画面が表示されている。
そこでもう一段掘り下げてみたら、
Dockerコンテナは一つの仮想環境であるという考え方が大事だということに気付いた。

実際に立ち上げたmailpitサーバーの中に入ることができるので、コマンドで入ってみる。

$ docker exec -it mailpit sh
$ ls -l

すると、以下のような結果が表示される。

drwxr-xr-x    2 root     root          4096 Jan 27 21:19 bin
drwxr-xr-x    5 root     root           340 Apr 15 01:50 dev
drwxr-xr-x    1 root     root          4096 Apr 15 01:50 etc
drwxr-xr-x    2 root     root          4096 Jan 27 21:19 home
drwxr-xr-x    1 root     root          4096 Jan 27 21:19 lib
-rwxr-xr-x    1 root     root      27283618 Apr  5 10:05 mailpit
drwxr-xr-x    5 root     root          4096 Jan 27 21:19 media
drwxr-xr-x    2 root     root          4096 Jan 27 21:19 mnt
drwxr-xr-x    2 root     root          4096 Jan 27 21:19 opt
dr-xr-xr-x  287 root     root             0 Apr 15 01:50 proc
drwx------    1 root     root          4096 Apr 15 02:08 root
drwxr-xr-x    3 root     root          4096 Jan 27 21:19 run
drwxr-xr-x    1 root     root          4096 Apr  5 10:05 sbin
drwxr-xr-x    2 root     root          4096 Jan 27 21:19 srv
dr-xr-xr-x   11 root     root             0 Apr 15 01:50 sys
drwxrwxrwt    1 root     root          4096 Apr 15 01:50 tmp
drwxr-xr-x    1 root     root          4096 Jan 27 21:19 usr
drwxr-xr-x    1 root     root          4096 Apr  5 10:05 var

これでようやく合点がいった。ここには一つのOSが存在しているのだ。
今回localhost:8025で表示されている画面は、このコンテナ内のOS上で動作しているMailpitアプリケーションの管理画面である。

つまり、今回localhostでつないだのはxamppの中のディレクトリではなくて、docker環境の中だったのだ。
まるでyamlを置いただけで管理画面が立ち上がったように見えたのは、単なる勘違いだった。初歩的な気付き。

メールを送ってみる

非常に簡素なphpファイルを用意して、メールを送ってみる。

<?php

$host = '127.0.0.1';
$port = 1025;

$fp = fsockopen($host, $port, $errno, $errstr, 10);
if (!$fp) {
    die("Connection failed: $errstr ($errno)");
}

function sendCmd($fp, $cmd) {
    fwrite($fp, $cmd . "\r\n");
    echo fgets($fp, 512);
}

// サーバ応答
echo fgets($fp, 512);

// SMTPコマンド
sendCmd($fp, "HELO localhost");
sendCmd($fp, "MAIL FROM:<test@example.com>");
sendCmd($fp, "RCPT TO:<dev@example.com>");
sendCmd($fp, "DATA");

// メール本文
fwrite($fp, "Subject: Mailpit Test\r\n");
fwrite($fp, "From: test@example.com\r\n");
fwrite($fp, "To: dev@example.com\r\n");
fwrite($fp, "\r\n");
fwrite($fp, "This is a test mail via Mailpit.\r\n");
fwrite($fp, ".\r\n");

echo fgets($fp, 512);

// 終了
sendCmd($fp, "QUIT");

fclose($fp);

echo "Done\n";

これでphpファイルを実行してみると、
Mailpit Mailpit メールが送受信できていることが確認できた。

Mailpitなぜなぜ

今のところMailpitでメールが送れたように見えているので、なんでメールが送れたんだろう?と疑問が湧いた。
メール送信というのは、ドメインを取得してメールアカウントを指定して送信するものであるから、どっちも取得してないのになんでメールが送れているのか?

答えは単純で、MailpitはFromヘッダを単なる文字列として処理しているだけである。
なので、別にアドレスもアカウントも何も必要なくて、ただ画面表示しているだけ。

じゃあMailpitで何をするの、というと「生成されるメールの内容を事前チェックできる」という点で利用されている。
例えば改行とか、変数の展開、文字コード、ToやCCの設定、添付ファイルの確認などである。
つまりアプリがメールを送信するとき正しくデータを整形できているかを確かめることができるということになる。
ちょっと脱線してしまったが、これがMailpitの役割である。

開発環境としてのDockerとサービス実行環境(独立して動くアプリ)としてのDocker

Dockerは用途として「開発環境」と「サービス実行環境(独立して動くアプリ)」として使われる。
開発環境としてのDockerとは、コンテナを起動するとイメージに含まれるWebサーバーやPHPなどのプロセスが起動し、/var/www/html にローカルのディレクトリ(例:/xampp/htdocs)がマウントされ、そのコードを参照して動作する。
サービス実行環境としてのDockerとは、コンテナを起動すると特定のアプリケーション(例:mailpit)が1つのプロセスとして動作し、ポート経由でローカルからリクエスト/レスポンスが可能になる。
この2つの違いは、コンテナ内で完結するか、ローカルコードを利用するかの違いでしかない。

まとめ

ここまで調べて、ようやくxamppとdockerの関係が理解できてきた。
dockerは環境を提供する、という曖昧な理解から「ローカルコードをマウントしたり、コンテナ内のリソースで完結したりする」という部分まで掘り下げられたのは大きい。
今後はもっと実務で活用していって、便利な使い方を発掘していきたい。