Dockerを触り始めて1日目の人が教えるDockerfile入門
Dockerを学び始めたときに、Dockerfileの書き方とイメージのビルドを試した記録。
過去の記事(Qiitaから移行)
この記事は公開当時の知識・環境に基づいて書いたものです。現在の仕様に合わせた更新・動作確認は行っておらず、内容の正確性や動作を保証するものではありません。
Dockerってなんとなく分かった!コマンドもHelloWorldできたので実践してみよう!という人が書いた記事です。 同じような状況の方の参考になれば幸いです!
重要
昨日Dockerを触り始めた人が学習した内容をアウトプットするために随筆した記事です。間違っていることが多数存在する可能性があります。
注意
Linux系のコマンドがわからない人は少しつらいかもしれません。(Dockerfile内には基本的にコマンドを書き込んでいきます。)
Dockerのコマンドで分かりやすい解説
https://qiita.com/wMETAw/items/34ba5c980e2a38e548db
Dockerfileとは?
中身はテキストファイルです。
元となるイメージに対して、必要な設定(例えばapt-get)などを加えたイメージが作成できます。
例えば、Apacheイメージだけでは何もページがありませんが、ポートの変更、ファイル(htmlやcssなど)を追加したイメージを作ることができます!
つまり、プログラミングをして元のデータに〇〇をして△△をするといった感じです。(ここにコマンドの知識が必要となってきます。)

実践
試しにApacheにHelloWorldと表示されるHTMLファイルが搭載されているイメージを作ってみる
Dockerfile
#1
FROM httpd:2.4.52
#2
COPY ./index.html /usr/local/apache2/htdocs
#3
WORKDIR /usr/local/apache2/htdocs/
#4
RUN ["apt","update"]
RUN ["apt","install","-y","curl"]
RUN ["touch","test.html"]
RUN echo 'Hello World 2' >> ./test.html && \
echo 'good!' >> ./test.html
#5
ENTRYPOINT httpd\
&& curl localhost\
&& curl localhost/test.html
index.html
<!DOCTYPE HTML>
<html lang="ja">
<head><meta charset="utf-8"><title>Test</title></head>
<body>Hello World!</body>
</html>
解説
#1 FROM
今回は複雑なことを扱わないので公式バージョンを利用します。ここの説明だけ少し長いです。
Dockerfile内のFROMはベースとなるイメージを指定したものになります。(リファレンス) GUIベースだとDockerHubで検索します。 例えば今回の場合はApache(httpd)なのでApacheと検索してみます。
そうすると、イメージ一覧が出てくるので、使いたいものをクリックしてみましょう。
Dockerの醍醐味である環境が同じものを複数用意できるという特性上、バージョンを指定してあげたほうが良いらしいです。
そのため、DescriptionにSupported tags and respective Dockerfile linksとありますから、そこから利用したいイメージを探せば良いです。alpineとかslimなど色々あり、どれを選べばいいの?となりますが、バージョン・OS・Slimの3つを利用者側が選択すれば良いわけです。
OSについて
| 名称 | 説明 |
|---|---|
| 公式(alpineなど何もついていない) | 作成者が用意している基本的なイメージ |
| alpine | 軽量重視Linuxディストリビューション。軽量化しているので必要なライブラリがない可能性がある。初心者向けではないらしい。しかしその分ファイルサイズは小さくなる。 |
| bullseye,buster,stretch,jessie | Debian。安定して使うことができる。左からバージョン11,10,9,8 |
| windowsservercore | Windows環境。 |
Slimについて
必要でない部分をそぎ落としたバージョンのことです。調べている感じ、
- 軽量化
- alpine>slim>Debian
- ファイルサイズ
- alpine<slim<Debian
という感じがする。(詳しくないのであいまいな感じです)
https://prograshi.com/platform/docker/docker-image-tags-difference/
#2 COPY
ファイルをコピーします。
COPY [Dockerfileからの相対パス] [コンテナ内のパス]
という形で指定します。
WORKDIR・RUN
さて、COPYにて指定したフォルダにファイルを置くことはできましたが、今度は任意の場所にコンテナ内からファイルを作成してみましょう!
#3 WORKDIR
WORKDIR パスにて、コンテナ内のどのフォルダで作業するか決めます。Linuxのcdコマンドと似た感覚です
#4 RUN
RUN ["コマンド",~]にて実行するコマンドを指定します。これはイメージの作成時に実行されます。配列になっていますが、すべての要素が半角スペース区切りで実行されます。配列を使わないことも可能です。複数行にわたって記入するときは\を利用しましょう。
#5 ENTRYPOINT・CMD
本サンプルではENTRYPOINTを利用しましたが、仲間としてCMD、そして実行時の引数(docker run packagename 実行するコマンドが存在します。
こちらで記入したものはコンテナ生成時に実行されるものです。このサンプルではhttpdを起動し、curlにてlocalhostを確認しています。
ENTRYPOINTがあれば強制的に実行(CMDと引数は実行されない)、
ENTRYPOINTがない場合には、CMDは引数が設定されていない時に実行、引数が設定されていればそちらを実行します。
ビルドする
Dockerfileなどが置いてあるディレクトリにて次のコマンドを実行します。
docker build -t イメージ名:タグ名 Dockerfileのディレクトリ
# 実行例
docker build -t miyayu/apachetest:1.0 .
Docker imagesをして作ったイメージがあればOKです。
実行する
docker run -rm イメージ名:タグ名
# 実行例
docker run -rm miyayu/apachetest:1.0
# 出力
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
(略)
<!DOCTYPE HTML>
<html lang="ja">
<head><meta charset="utf-8"><title>Test</title></head>
<body>Hello World!</body>
</html> % Total (略) 0Hello World 2
good!(略)
チャレンジ問題
AH00558エラーに関してはこちらの記事が参考になるかと思います。チャレンジ問題としてエラーを解決してみてください!!
https://ex1.m-yabe.com/archives/2965
ヒント
コマンドを実行する方法
設定ファイルがどこにあるか探すためにlsなどを使いたいですか?そんなときにはEntrypointに/bin/bashというコマンドを追加してみましょう!(設定ファイルは/usr/local/apache2/conf/httpd.confです。)
docker run時に-itをつけることでコンテナを操作することが可能になります。(exitコマンドで終了できます。)
ちなみに--rmオプションはexit時にデータを削除するものなので、保存したデータをもう一度見たいなど思ったら必要に応じて外してみてください。
あ、根本的な解決はDockerfile内で行ってくださいね?
コマンドを実行する方法の答え(クリックで開く)
Dockerfile
ENTRYPOINT httpd\
&& curl localhost\
&& curl localhost/test.html\
&& /bin/bash
sedコマンドをRUN内で実行してみましょう!(ディレクトリ移動も忘れずに)
実行するコマンドを確認する(クリックで開く)
sed -i -e 's/#ServerName www.example.com:80/ServerName www.example.com:80/g' httpd.conf
文字列を置き換える方法の答え(クリックで開く)
Dockerfile
WORKDIR /usr/local/apache2/conf/
RUN ["sed","-i","-e","s/#ServerName www.example.com:80/ServerName www.example.com:80/g","httpd.conf"]