docker build でイメージ作成 - 初心者向け手順
はじめに
Dockerは、アプリケーションや関連ライブラリをひとまとめにして扱いやすい形にするためのツールです。
多くの場合、Dockerを使うと自分のパソコンと他の環境の違いを気にせず開発できるようになります。
しかし、初心者がDockerを使い始めるときに迷いやすいポイントが「docker build」によるイメージの作成です。
何から手を付ければよいか、どのコマンドが重要なのかをしっかり把握できていないと、思ったようにコンテナを動かせず苦労することがあります。
そこで本記事では、docker build でイメージを作成する初心者向けの手順を中心に、イメージとは何なのか、どんなところで役立つのかを具体例と合わせて丁寧に説明します。
日常的な実務でどのように活用されているかにも触れながら、初心者が一歩一歩理解を深められる構成にしています。
この記事を読むとわかること
- Dockerイメージ とコンテナの違いと、それぞれの役割
- docker build コマンドの基本的な使い方
- 実務でどのようにイメージ作成が活かされるかの具体的なシーン
- Dockerfile の基本構造と、作成時のコツ
- docker build 周辺で起こりやすいトラブルと対処法
Dockerの基本概念
Dockerをはじめて触る方は「そもそも何ができるのか」を整理すると理解しやすくなります。
ここではコンテナとイメージの概要を確認し、docker build というコマンドがどういう役割を持つかイメージしやすくなるように説明します。
Dockerイメージとコンテナの違い
Dockerを使うときに重要なのが、イメージ と コンテナ という2つの概念です。
イメージは、コンテナを動かすための“設計図”のような存在です。
実行環境に必要なアプリケーションやライブラリをまとめてあり、そこからコンテナという実行状態を作り出せます。
一方のコンテナは、実際に動作している“実体”にあたります。
具体的には、イメージを元に作成されたプロセスであり、その中でアプリケーションが動きます。
イメージを変更せずに複数のコンテナを立ち上げることも可能です。
そのため、アプリケーションの動作環境を同じ状態で複数用意したいときや、開発チームで統一したいときなどにとても便利です。
docker buildで何ができるのか
Dockerの世界では、イメージを作るためにはdocker build が欠かせません。
これは、後述するDockerfileに書かれた命令に従ってアプリケーションやライブラリをまとめ上げ、最終的にイメージという形にしてくれます。
初心者の方の中には「docker runでコンテナ起動すればイメージが勝手にダウンロードされるのでは?」と思う人もいるかもしれませんが、それは公開リポジトリにあるイメージを取ってくる場合です。
自分で用意したアプリケーションを含む独自イメージを作りたいときには、必ずdocker build の手順を踏む必要があります。
このあたりを理解しておくと、なぜdocker buildが重要なのかが少しはっきりしてくるでしょう。
docker buildを始める前に準備しておきたいこと
いざ「docker buildを使ってイメージを作成したい」と思っても、Dockerfileをどう書けばいいのか、どのように動くのかがわからないと始まりません。
そこで準備として大まかな流れを整理しておきます。
Dockerのインストール
まずは自分のパソコンやサーバーなど、Dockerを使いたい環境にDockerを導入する必要があります。
一般的には公式サイトからインストーラーを入手し、それを実行してインストールするだけで使えるようになります。
インストール手順はOSごとに違いがありますが、公式ドキュメントを見ると、初心者にもわかりやすい手順で紹介されているはずです。
コンテナを使うにはOSレベルでのサポートが必要なため、環境によっては追加の設定が必要ですが、基本的にDockerが動くようになれば準備完了です。
Dockerfileの基礎構文
Dockerfile はテキストベースでDockerイメージを構築するための指示を書き込むファイルです。
ここでは代表的な命令をいくつか簡単に見てみましょう。
FROM
ベースイメージを指定します。
例: FROM ubuntu
RUN
コンテナの中で実行したいコマンドを指定します。
例: RUN apt-get update && apt-get install -y curl
COPY
ホスト上のファイルをコンテナ内へコピーします。
例: COPY . /app
WORKDIR
コンテナ内で作業ディレクトリを移動します。
例: WORKDIR /app
CMD
コンテナが起動するときに実行されるコマンドを指定します。
例: CMD ["python", "app.py"]
これらの命令を組み合わせてイメージを作り込むわけですが、それぞれが実行されるたびに「レイヤー」が積み重なっていくとイメージの形が完成します。
このレイヤーの概念は後で紹介するキャッシュ活用時にも関わってきますので、頭の片隅に入れておくとよいでしょう。
docker buildコマンドの実行手順
ここではDockerfileの作成例を示しながら、実際にdocker build コマンドを実行してイメージを作るまでの流れをざっくり追っていきます。
初心者の方でもつまずきにくいよう、できるだけシンプルな例を使います。
Dockerfileの作成例
たとえば、Node.jsの環境を利用したアプリケーションを動かしたいとしましょう。
アプリケーション自体は、server.js
という簡単なウェブサーバースクリプトだけだと仮定します。
次のようにDockerfileを作成してみます。
FROM node:18-alpine WORKDIR /app COPY server.js /app RUN npm install CMD ["node", "server.js"]
FROM node:18-alpine
Node.jsがあらかじめ入っている小型のイメージをベースにしています。
WORKDIR /app
作業ディレクトリを/app
に設定しました。
COPY server.js /app
ホスト側のserver.js
をコンテナの/app
ディレクトリにコピーします。
RUN npm install
必要なnpmパッケージをインストールします。
(もしpackage.json
がある場合はそれもCOPYしてから実行するといいでしょう。)
CMD ["node", "server.js"]
コンテナが起動したタイミングでserver.js
を実行し、ウェブサーバーを立ち上げるということになります。
コマンドの実行
Dockerfileを作成したら、ターミナルやコマンドプロンプトでdocker build を実行します。
一般的な書式は次の通りです。
docker build -t my-node-app .
-t my-node-app
イメージに名前を付けています。my-node-app
というリポジトリ名で、この例ではタグは付けずに最新と扱われます。
.
現在のディレクトリ(ここにDockerfileがある想定)を指定しています。
コマンドを実行すると、DockerはDockerfileの内容を一行ずつ読み込んで指示どおりにイメージを組み上げていきます。
イメージ作成後の確認
イメージが無事に作成されると、docker images
というコマンドで一覧を確認できます。
docker images
ここで、先ほど指定したmy-node-app
という名前のイメージがリストに表示されていれば成功です。
このイメージを使ってコンテナを起動するには、次のようにコマンドを実行します。
docker run -p 3000:3000 my-node-app
こうすると、ローカル環境のポート3000番とコンテナ内の3000番がつながり、ブラウザからhttp://localhost:3000
にアクセスすれば、server.js
が提供するアプリケーションの画面が表示されるはずです。
コンテナが実際に起動している間は、ホスト上のターミナルにログが出力され続けることがあります。開発作業中にログをリアルタイムで見たい場合には、そのまま前面で動かして問題ないでしょう。
docker buildと実務での活用シーン
「自分のパソコンでアプリケーションが動いたから、とりあえずOK」というだけでは、Dockerを使うメリットを十分に活かせていないかもしれません。
実際の開発現場では、docker build で作成したイメージを使うことで、さまざまな課題を解決しています。
開発環境の統一
チームで開発を進めるとき、メンバーそれぞれのパソコン環境が異なると設定や依存ライブラリの違いで混乱が起きがちです。
そこでDockerイメージを共有すれば、同じ環境を簡単に再現できます。
新しいメンバーが加入したとき
イメージを取得してコンテナを立ち上げるだけで、開発環境が整います。
バージョンの食い違い対策
設定ファイルや依存ライブラリをイメージ側で固定しておくことで、各マシンで違う状況になるのを防ぎます。
こうした利点により、「自分の環境では動くけど他の人の環境では動かない」といった典型的なトラブルを減らすことができます。
CI/CDパイプラインへの組み込み
継続的インテグレーション(CI)や継続的デリバリー(CD)のプロセスでも、docker build は重要です。
アプリケーションに新たな機能が追加されるたびに、自動的にイメージをビルドしてテストを実行し、そのイメージを使って本番環境へデプロイするという流れは一般的です。
このとき、Dockerfileが共通の仕様になっていれば、テスト用と本番用で大きく環境を切り替えずにすむのは大きな魅力です。
Dockerイメージをそのまま本番へ持っていくことで、ローカルで動かしていたものと同じ状態が再現されます。
チーム開発での効率化
特に大規模プロジェクトになると、バックエンド、フロントエンド、データベースなど複数のコンテナを同時に動かすことがあります。
その際、一つひとつ個別に環境をセットアップするのは非効率です。
あらかじめDockerfileを整備し、docker build でイメージを作成しておけば、新しいコンテナを素早く起動できます。
また、それぞれのコンテナが役割分担して連携しているので、ローカル開発でも実際に近い構成を試せるようになります。
その結果、コードの互換性を検証しやすくなると同時に、トラブルシューティングも楽になることが多いです。
docker buildを使いこなすためのヒント
初心者向けの基本手順を押さえたうえで、次のステップとして活用度を高める工夫を見ていきましょう。
ここでは特に、キャッシュ、マルチステージビルド、セキュリティを意識したイメージの作り方に注目します。
キャッシュを活用する
Dockerfileの命令は基本的に上から下へ順に実行され、変更がなければ前のビルド結果を再利用するキャッシュが働きます。
このキャッシュをうまく活用すると、docker build の処理時間を短縮できます。
例えば、変更がほとんどない箇所で時間のかかる処理(大きなライブラリのインストールなど)をまとめて実行しておくと、後の修正で再ビルドしても最初の工程は再利用されやすくなります。
ただし、Dockerfile の命令の順番次第でキャッシュヒットが大きく変わるため、頻繁に変化するファイル(ソースコードなど)はできるだけ後ろに持ってきたほうが効果的です。
また、逆にキャッシュが原因で思わぬ不整合が起きる場合もあるため、時には--no-cache
オプションでキャッシュを無効化することもあります。
マルチステージビルドを試してみる
コンパイルが必要な言語を扱うときに便利なのが、マルチステージビルド という方法です。
これは、1つのDockerfile内で複数のFROM
を使い分け、ビルド用のイメージと、実際に本番で動作させるイメージを分離する手法です。
例えば、最初のステージでソースコードをコンパイルし、その成果物だけを軽量なベースイメージにコピーして最終的なイメージを仕上げるという流れを組めます。
結果として、不要な開発ツールを本番環境から省けるうえに、イメージサイズも小さくなるメリットがあります。
以下はイメージの例です。
# 1つ目のステージ: ビルド用 FROM node:18-alpine as builder WORKDIR /app COPY . . RUN npm install && npm run build # 2つ目のステージ: 実行用 FROM node:18-alpine WORKDIR /app COPY /app/dist /app CMD ["node", "main.js"]
このようにステージを分けることで、実行時に必要なファイルだけを本番イメージへ含められます。
大規模なアプリケーションでは、このやり方が役立つ場合があります。
セキュリティとサイズ最適化
Dockerイメージを配布するときは、セキュリティの観点とサイズ最適化の観点からも注意が必要です。
不要なファイルを含めない
ソースコードの中に含まれているテスト用データや機密情報などは、コピーしないようにDockerfileを工夫しておくとトラブルを防げます。
不要なパッケージを入れない
インストールしていないと動かないもの以外は極力省いて、イメージをスリムに保つのがおすすめです。
イメージのアップデート
使っているパッケージに脆弱性が見つかることがあります。イメージを作る際にこまめにアップデートコマンドを走らせることで、古いパッケージに由来する問題を減らせる場合があります。
トラブルシューティングのポイント
初心者のうちは、docker build 周りで躓くことが珍しくありません。
たとえばビルド中のエラーや、思ったほどサイズが減らないなど、さまざまなハードルが出てきます。
ここでは、ありがちなトラブル例と解決策のヒントを紹介します。
ビルド時のエラー
Dockerfileの記述ミスや、指定したパッケージが見つからないなどの理由でビルドが失敗することがあります。
次のような対処を考えてみるとよいでしょう。
ログの確認
エラーの原因がわからないときは、ターミナルに表示されるログを上から順にチェックし、どのステップで失敗しているかを特定しましょう。
Dockerfileの構文チェック
FROM、RUN、COPYなどの命令を正しく書いているかを改めて確認します。
依存関係の確認
Dockerfile内部で行っているインストールコマンドに古いリポジトリや不要なライブラリが含まれていないか、あるいはインターネットへのアクセスが制限されていないかもチェックしてみてください。
イメージが思ったより大きい
イメージサイズが大きくなるのはよくある悩みです。
ビルドした結果、予想以上に容量を消費してしまい、アップロードやデプロイに時間がかかるケースがあります。
軽量ベースイメージの選択
例えば、DebianベースではなくAlpineベースのイメージを使うなど、もともとのサイズが小さいイメージを活用する方法があります。
マルチステージビルドを活用
ビルド用のツールチェーンやドキュメントなどを本番イメージに含めずに済むように工夫すると、かなり削減できることが多いです。
不要ファイルの削除
Dockerfileの中で生成されるキャッシュファイルや一時ファイルを適切なステップで削除しておくと、最終的なイメージサイズを抑えられます。
コンテナ起動時の不具合
ビルドが成功してイメージができても、docker run
でコンテナを起動したら予期しないエラーが出ることがあります。
ポートの指定ミス
コンテナ内部で使われているポートと、docker run -p
でマッピングするポートが一致しているか確認が必要です。
ファイルのパスや作業ディレクトリの設定
DockerfileのCOPY
やWORKDIR
の記述が誤っていると、実行ファイルや設定ファイルが見つからない状態になることがあります。
依存サービスの起動確認
他のコンテナや外部サービスを利用する場合には、それらが先に起動しているか、あるいは接続先URLやホスト名が正しいかをチェックしましょう。
複数のコンテナ間を連携させるときは、Docker Composeを使うと設定をまとめて管理しやすくなります。イメージを複数作る場合でも、それぞれDockerfileを用意しDocker Composeで一括実行することで、連携環境を簡単に立ち上げられます。
まとめ
ここまで、docker build でイメージを作成する初心者向けの基本手順から、実務シーンでの活用方法、さらにはトラブルシューティングのポイントまで幅広く紹介しました。
Dockerをうまく使いこなすと、環境構築やバージョンの違いによる問題を大幅に減らせます。
チーム開発やCI/CDパイプラインにもシームレスに取り入れられることから、学ぶ価値は十分にあるでしょう。
- Dockerfileを用意し、docker build でイメージを作る
- 作成したイメージからコンテナを起動し、アプリケーションを実行する
- 不要なファイルを含めない、キャッシュやマルチステージビルドを活用して効率化する
- トラブルが起きたら、ログやDockerfileの構成を丁寧に見直す
この流れを一通り理解しておけば、今後より複雑なアプリケーションに取り組む際も応用が効きます。
さらに実務では、イメージを自社のプライベートリポジトリに保存したり、CI/CDと連携して自動ビルド・自動デプロイを行ったりなど、便利な使い方がたくさんあります。
まずは小さなプロジェクトやサンプルで、docker build を実際に動かして、Dockerfileに触れる機会を増やしてみてください。
慣れてくると、ローカル環境と本番環境の整合性を調整するのがかなり楽になるはずです。
ここで紹介したヒントを活用し、みなさんがDockerイメージ作成でつまづく場面を減らせれば幸いです。