👁 0

Dockerfileの基本文法

この講座では、Dockerfileを使った独自イメージの作成方法について学びます。

  • Dockerfileの役割とメリット
  • 基本命令(FROM・COPY・CMD)
  • イメージのビルド(docker image build)
  • ポートの接続(-pオプション)

1. Dockerfileとは

前の講座では、Docker Hubから既存のイメージを取得する方法を学びました。本講座では、もう一つの方法である「Dockerfileを用いて、独自のイメージを作成する方法」について解説します。

1.1 Dockerfileの役割

Dockerfileとは、Dockerイメージを作成するための手順を記したテキストファイルのことです。

具体的には、既存のイメージ(LinuxやGo言語など)をベースにしつつ、OSの環境設定を行ったり、必要なミドルウェアやライブラリをインストールしたり、開発したアプリケーションのコードをコピーしたり、あるいはコンテナ起動時に実行するコマンドを指定したりといった、独自のカスタマイズを加えるための指示書となります。

既存のイメージをそのまま使うのではなく、Dockerfileを使って独自のイメージを作ることには大きなメリットがあります。

まず、サーバの構築手順がテキストファイルとして残るため、「誰がいつ作っても同じ環境」を再現できるというInfrastructure as Code(コードによるインフラ管理)が実現できます。

また、自分の作ったプログラムコードをイメージの中に定義することができるため、どのサーバでも即座にアプリケーションを動かせるようになります。さらに、巨大なイメージファイルそのものを渡さなくても、軽量なテキストファイルであるDockerfileを共有するだけで、チームメンバー全員が同じ開発環境を手に入れることができます。

1.2 イメージ作成の流れ

Dockerfileからイメージを作成する流れは非常にシンプルです。まずはテキストエディタで「Dockerfile」という名前のファイルを作成し、そこに構築手順を記述します。

次に、作成したファイルをもとにdocker image buildコマンドを実行することで、Dockerに対してイメージの作成を命令します。すると、Dockerがファイル内の手順を上から順に実行し、独自のDockerイメージが完成するという仕組みです。

2. Dockerfileの基本文法

基本的なDockerfileの文法を説明します。

2.1 FROM

FROMは、Dockerfileの先頭に記載するもので、新しく作成するイメージの土台(ベース)となるイメージを指定するためのものです。

FROM nginx

この記述は、nginxという既存のイメージをベースにして、そこから新しいイメージの作成を始めることを意味しています。

また、イメージ名の後に「タグ」をつけることで、使用するバージョンやOSの種類を細かく指定することもできます。

FROM nginx:alpine

コロン(:)の後ろにあるalpineがタグにあたります。このように記述することで、「nginxイメージの中でも、軽量なalpine版を使いたい」といった具体的な指定が可能になり、意図しないバージョンの変更を防ぐことができます。なお、タグを省略した場合は、自動的に最新版(latest)が使用されます。

FROM命令には他にもマルチステージビルドなどで使用する機能がありますが、今後のハンズオンで必要になった段階で説明します。

実際にどのようなベースイメージが利用可能かは、Docker Hubの公式サイトから確認することができます。 ただし、公開されているイメージは膨大であり、すべてのベースイメージを事前に把握しておくことは困難です。そのため、まずはハンズオンなどを通じて「自分がよく使う代表的なベースイメージ」をいくつか押さえておき、新しい環境が必要になったタイミングで随時調べていく、というスタンスで進めていけば問題ありません。

Docker Hub

良く使われるベースイメージの一覧を以下に記載しておきます。

イメージ名 説明 主な用途
alpine 軽量Linux(約5MB) 最小構成のコンテナ、軽量化が必要な場面
ubuntu 汎用Linux 開発環境、多くのパッケージが必要な場面
debian 安定性重視のLinux 本番環境、長期運用
node Node.js実行環境 JavaScriptアプリケーション
python Python実行環境 Pythonアプリケーション、機械学習
golang Go言語実行環境 Goアプリケーション
nginx Webサーバ 静的サイト配信、リバースプロキシ
httpd Apache Webサーバ Webサイト配信
postgres PostgreSQLデータベース リレーショナルDB
mysql MySQLデータベース リレーショナルDB
redis インメモリデータストア キャッシュ、セッション管理

多くのイメージにはalpineタグ(例:node:alpinepython:alpine)が用意されており、軽量版として利用できます。

2.2 COPY

COPYは、自分のPC(ホスト)にあるファイルやフォルダを、コンテナの中に配置するための命令です。

COPY index.html /usr/share/nginx/html/

この記述は、PC上の同じフォルダにあるindex.htmlというファイルを、コンテナ内の/usr/share/nginx/html/というディレクトリの中にコピーすることを意味しています。Webサーバに表示させたいHTMLファイルや、アプリケーションのソースコードをコンテナに取り込む際によく使用されます。

また、特定のファイルだけでなく、フォルダ内のすべてのファイルをまとめてコピーすることも可能です。

COPY . .

この記述は、「現在のディレクトリにあるすべてのファイル(一つ目のドット)」を、「コンテナ内の作業ディレクトリ(二つ目のドット)」にコピーする、という指定になります。開発したソースコード一式をコンテナに持ち込む際などに頻繁に使用される書き方です。

2.3 CMD

CMDは、コンテナが起動したタイミングで実行される「デフォルトのコマンド」を指定するための命令です。

CMD ["echo", "Hello, Docker!"]

この記述は、コンテナが立ち上がった瞬間に echo という「文字を出力するコマンド」を実行することを意味しています。

コマンドや引数(ひきすう)はカンマ区切りで指定しますが、実際に実行されるコマンドは echo "Hello, Docker!" となります。

このように、CMD命令を使うことで、コンテナ起動時に「何をさせたいか」を定義することができます。Webサーバであればサーバの起動コマンドを、バッチ処理であればその実行コマンドを記述します。

良く使われるCMDの記載例をいくつか提示します。

用途 CMD 説明
Nginx CMD ["nginx", "-g", "daemon off;"] Webサーバをフォアグラウンドで起動
Node.js CMD ["node", "app.js"] Node.jsアプリケーションを起動
Python CMD ["python", "app.py"] Pythonスクリプトを実行
Go CMD ["./main"] Goのビルド済みバイナリを実行
Java CMD ["java", "-jar", "app.jar"] Javaアプリケーションを起動
npm CMD ["npm", "start"] package.jsonのstartスクリプトを実行
Shell CMD ["/bin/sh"] シェルを起動(デバッグ用)

2.4 まとめ(命令一覧)

今回使用したdockerfileの記載を下記にまとめておきます。

命令 説明
FROM <イメージ名> ベースイメージを指定
COPY <ホスト> <コンテナ> ファイルをコンテナにコピー
CMD ["コマンド", "引数"] コンテナ起動時に実行するコマンドを指定

3. 今回新しく使用するDockerコマンド

この講座で新しく登場するDockerコマンドの一覧です。

コマンド 説明
docker image build --tag <イメージ名> . Dockerfileからイメージを作成
docker container run -p <ホスト>:<コンテナ> ポートを接続してコンテナを起動

3.1 docker container runの-pオプション

今回、docker container runで実行する際に、-pオプションを使用して起動するポートを指定します。

-pは、コンテナ内の特定ポートに、自分のPC(ホスト)からアクセスできるようにポートを接続(公開)して起動するためのオプションです。

docker container run -p 8080:80 my-image

この記述は、自分のPCのポートとコンテナのポートを接続して起動することを意味しています。

-p8080:80と記述することで、「自分のPCの8080番ポート(左側)」に来たアクセスを、「コンテナ内の80番ポート(右側)」に転送する設定になります。

例えばNginxのようなWebサーバは、HTTP通信の標準である80番ポートで起動します。しかし、PC側の80番ポートは他のアプリケーションですでに使用されていたり、セキュリティの権限によっては使用が制限されていることがあります。

そのため、このオプションを使って「コンテナ内では80番ポートで起動させるが、それを自分のPC(ローカル)からは8080番ポートとして扱う」という設定を行います。

4. シンプルなDockerfileを実行しよう

シンプルなDockerfileを作成し、イメージの作成およびコンテナの起動を行うハンズオンを実施します。

このハンズオンでは、シンプルなHTMLファイルを作成し、それをNginxのサーバで動かすためのDockerfileを作成し、コンテナとして実行していきます。

4.1 Visual Studio Codeのインストール

Dockerfileを記載するために、テキストエディタが必要となります。今回のハンズオンでは、Visual Studio Codeを用いて、Dockerfileを作成していきます。

Visual Studio Codeがまだインストールされていない場合、下記のサイトよりインストールをお願いします。

Visual Studio Code

4.2 Dockerfileを用意しよう

基本命令を使った実際のDockerfileを見ていきます。

まず、任意の場所に作業用のフォルダを作成し、Visual Studio Codeの「ファイル」→「フォルダーを開く」から、作成したフォルダを開きます。

任意のフォルダ  ← このフォルダを作成

Dockerfileを作成します。Visual Studio Codeのエクスプローラーでフォルダを右クリックし、「新しいファイル」を選択してDockerfileという名前で作成してください。

任意のフォルダ
└── Dockerfile  ← このファイルを作成

作成したファイルに以下の内容を記述して保存します。

FROM nginx:alpine

COPY index.html /usr/share/nginx/html/index.html

CMD ["nginx", "-g", "daemon off;"]

このDockerfileは、ローカル環境にあるindex.htmlを用いて、NginxでWebサーバを起動し、Webサイトとして表示させるためのものです。

FROM nginx:alpine

まずはこの部分で、ベースイメージとしてnginx:alpineというイメージを使用します。これは、alpineという軽量なOSに、サーバソフトウェアであるNginxを事前にインストールしたベースイメージです。

📝 alpineとは
alpineは、最低限の機能に抑えたシンプルなLinux OSで、コンテナの実行によく使われるOSです。OSは用途に応じて軽量に実行できることが理想なため、軽量OSであるalpineと相性が良いです。
COPY index.html /usr/share/nginx/html/index.html

これは、ローカル環境にあるindex.htmlというファイルを、/usr/share/nginx/html/index.htmlという名前でコンテナの中にコピーするコマンドです。

なお、/usr/share/nginx/html/index.htmlは、Nginxにおいて「デフォルトで表示されるHTMLファイル」を表すファイルです。

CMD ["nginx", "-g", "daemon off;"]

この記述は、コンテナが立ち上がった瞬間に nginx -g daemon off; というWebサーバのプログラムを実行することを意味しています。

ここで使用している -g は、Nginxの設定ファイルに記述するような設定内容を、コマンドラインから直接渡すためのオプションです。今回はこれを使ってdaemon off;という設定を直接効かせ、Dockerコンテナがすぐに終了してしまわないように制御しています。

このあたりはNginxの仕様となるため、今回は深く把握する必要はありません。「Nginxで起動したサーバがすぐに終了しないようにするために必要なもの」という程度の理解で構いません。

4.3 index.htmlを用意しよう

続いて、Dockerの中で使用するindex.htmlファイルを用意します。Visual Studio Codeのエクスプローラーでフォルダを右クリックし、「新しいファイル」を選択してindex.htmlという名前で作成してください。

任意のフォルダ
├── Dockerfile
└── index.html  ← このファイルを作成

作成したファイルに以下の内容を記述して保存します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Docker Hands-on</title>
</head>
<body>
    <h1>hello Docker!</h1>
</body>
</html>

4.4 イメージの作成

Visual Studio Codeにて、ターミナル→新しいターミナルのメニューをクリック知ると、下の方にターミナルが表示されます。ここでコマンドを実行していきます。

DockerfileからDockerイメージを作成(ビルド)します。

docker image build --tag my-image .

コマンドの最後の .(ドット)は、「現在のディレクトリにあるDockerfileを使用する」という意味の重要な記述です。--tag でイメージに my-image という名前を付けています。

作成されたイメージを確認します。

docker image ls

リストに my-image が表示されていれば作成成功です。

REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
my-image       latest    42f30c30f2b0   10 seconds ago   61.2MB
⚠️ 「COPY failed: file not found」エラーが出る場合
Dockerfileと同じディレクトリにindex.htmlファイルが存在しないか、ファイル名が間違っています。lsコマンドでファイルが存在することを確認し、ファイル名のスペルミス(大文字小文字を含む)がないか確認してください。
⚠️ 「no such file or directory」エラーが出る場合
コマンドを実行しているディレクトリが正しくない可能性があります。cdコマンドでDockerfileがあるディレクトリに移動してから、再度docker image buildを実行してください。末尾の.(ドット)を忘れないように注意してください。

4.5 コンテナの起動

作成したイメージからコンテナを起動します。

docker run -d -p 8080:80 --name first-container my-image
オプション 設定の基準
-d - ターミナルを占有せずにバックグラウンドで実行するため
-p 8080:80 PCの8080番ポートへのアクセスをコンテナの80番ポートへ転送するため
--name first-container コンテナを識別しやすい名前で管理するため

コンテナが起動しているか確認します。

docker container ls

以下のように、first-containerが表示され、STATUSUp になっていれば起動しています。

CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                  NAMES
9fde109a11e5   my-image   "/docker-entrypoint.…"   39 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp   first-container
⚠️ 「port is already allocated」エラーが出る場合
指定したポート(8080番)が既に他のアプリケーションやコンテナで使用されています。docker container lsで既存のコンテナを確認し、不要であれば停止・削除してください。または、-p 8888:80のように別のポートを指定して起動し直してください。

4.6 動作確認

ブラウザを開き、以下のURLにアクセスしてください。

http://localhost:8080

「Hello Docker!」というメッセージが表示されていれば、動作確認は成功です。

⚠️ ブラウザでアクセスできない場合
(1) コンテナが正常に起動しているかdocker container lsで確認してください。STATUSがUpになっていることを確認します。
(2) 別のアプリケーションが8080番ポートを使用している可能性があります。その場合は-p 8888:80のように別のポートを指定して起動し直してください。

4.7 不要リソースの削除

ハンズオンが終わったら、作成したリソースを削除(お片付け)します。

コンテナの停止

まずは動いているコンテナを停止します。

docker container stop first-container

停止したことを確認します。

docker container ls -a

ステータスがExitedとなっていれば、無事に停止しています(プロセスが終了しています)。

CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS                     PORTS     NAMES
9fde109a11e5   my-image   "/docker-entrypoint.…"   5 minutes ago   Exited (0) 6 seconds ago             first-container

コンテナの削除

停止したコンテナを完全に削除します。

docker container rm first-container

コンテナの一覧に表示されなくなれば、無事に削除されています。

docker container ls -a

イメージの削除

最後に、作成したイメージも削除します。

docker image rm my-image

イメージの一覧に表示されなくなれば、無事削除されています。

docker image ls

5. まとめ

この講座では、Dockerfileの基本について学びました。

  • Dockerfileは、Dockerイメージを作成するための手順を記したテキストファイル
  • FROMで土台となるベースイメージを指定する
  • COPYでホストのファイルをコンテナ内にコピーする
  • CMDでコンテナ起動時に実行されるデフォルトコマンドを指定する
  • docker image buildコマンドでDockerfileからイメージを作成できる
  • -pオプションでホストとコンテナのポートを接続する

6. 次のステップ

🎉 おめでとうございます!Dockerの基本操作とDockerfileによるイメージの作成まで体験できました。

ここまでで学んだ内容は、コンテナを扱ううえでの基本中の基本です。ここから先は、より実践的な内容に進みます。

講座名 学べること
マルチステージビルド 軽量なDockerイメージを作るためのビルド最適化
Dockerネットワーク コンテナ間通信の仕組みとネットワーク設定
Dockerストレージ ボリュームとバインドマウントによるデータ永続化
Docker Compose 複数コンテナの定義と一括管理
Amazon ECS / Fargate講座 AWSのコンテナ実行環境
ECSとFargateで本格的なWebアプリをデプロイしよう VPC・RDS・ECSを組み合わせた本格的なデプロイ

AWSでコンテナアプリケーションを動かせるようになりたい方は、ぜひ次のステップに進んでみてください。

この教材は役に立ちましたか?

いいねをたくさんいただけると、制作者の励みになり、より多くの講座が作れるようになります。

感想を一言(任意)

いただいたコメントは次の制作のヒントになります。ぜひお気軽にご投稿ください。

このコメントは他の受講生には公開されません。DevOps Camp運営が、教材改善のために確認します。

0 / 2000