Rubyと筋肉とギターとわたし

エンジニア二年目の雑魚です。プログラミング・ギター・筋トレのことをメインにブログを書いていきます。

Docker初心者が超絶簡単にDockerfileをまとめてみた その1

前回の記事で簡単なDockerfileを初めて作ってみました。

ですが、全くDockerfileの書き方について触れてなかった、というよりスルーしていたのでちょっとまとめてみたいと思います。
他にDockerfileの記事を書いている人はだいたいわかりにくい・・・

多分簡単です。慣れれば。

Dockerfileってなによ

簡単に言えば、「コンテナを作るときの説明書」および「手順書」のこと

Dockerfileのおかげで以下

  • dockerイメージを作成
  • コンテナ内で行うコマンド操作
  • 環境変数の設定
  • コンテナ内で動作させるデーモン実行

をビルド時に実行してイメージを作成したりします。

ね!簡単でしょ?

Dockerfileの命令一覧

命令 説明
FROM ベースイメージの指定
MAINETANER Dockerfileの作成者情報
RUN コマンド実行
VOLUME ボリュームのマウント
ADD ファイル/ディレクトリの追加
COPY ファイルのコピー
CMD デーモン実行
ENTRYPOINT デーモン実行
LABEL ラベルの設定
USER ユーザの指定
EXPOSE ポートのエクスポート
WORKDIR 作業ディレクトリの指定
ENV 環境変数の設定
ONBUILD ビルド完了後に実行される命令

上の表がDockerfileの命令です。 これを元にやっていきます。

今回はほんと簡単な命令しか書きません。
次回以降暇があれば記事にします。



実行環境

  • ubuntu16.04.1(elementary OS 0.4.1 Loki)
  • Docker version 17.12.0-ce

準備

わかりやすいようにディレクトリの準備をします。

$ cd ~ && mkdir docker-practice && cd !!$ && touch Dockerfile

homeディレクトリに移動してdocker-practiceディレクトリ作成&移動、Dockerfileを作成します。

FROM命令

DockerfileではコンテナはどのDockerイメージから生成するかという、「ベースイメージ」が必要なので、それをFROM命令で書いてあげます。

FROM イメージ名
or
FROM イメージ名:タグ名
or
FROM イメージ名@ダイジェスト

上記の形で書きます。
が、上2つだけ覚えておけばとりあえず大丈夫です。

たとえば、最新のubuntuイメージを取ってきたい場合は

FROM ubuntu:latest

でおk。超簡単。

試しにイメージを作ってみますか。
docker build -t <イメージ名> <Dockerfileのディレクトリ>で実行してみる(<イメージ名>:<タグ名>でタグをつけることができます)。

# 作成したDockerfileと同じディレクトリにいるはずなので"."でおk
$ docker build -t test .
Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM ubuntu:latest
latest: Pulling from library/ubuntu
d3938036b19c: Pull complete 
a9b30c108bda: Pull complete 
67de21feec18: Pull complete 
817da545be2b: Pull complete 
d967c497ce23: Pull complete 
Digest: sha256:9ee3b83bcaa383e5e3b657f042f4034c92cdd50c03f73166c145c9ceaea9ba7c
Status: Downloaded newer image for ubuntu:latest
 ---> c9d990395902
Successfully built c9d990395902
Successfully tagged test:latest

まあまあ時間かかりました。

ちゃんとDockerfileを元にイメージが作成されているか確認してみる。

$ docker images
REPOSITORY              TAG                IMAGE ID               CREATED           SIZE
test                                latest              c9d990395902        2 days ago          113MB
ubuntu                           latest              c9d990395902        2 days ago          113MB

できてますね。

他のディレクトリにあるDockerfileを指定する時は、ディレクトリパスをdocker buildの最後に書いてあげてください。

今書いたDockerfileを元に別のイメージ名にしてdocker buildしてみると、前よりかなり早くbuildが完了するはず。
これは、ubuntu:latestベースイメージがローカル環境にダウンロードされているためです。

同じイメージを使用するときはかなり早くbuildできます。

RUN命令

コンテナ上で実行するコマンドの命令です。
CentOS系のyumUbuntu系のapt-getを元に検索かけていけばいいと思いますよ(多分)。

さっきのイメージを元にApacheを入れてみたいと思います。

FROM ubuntu:latest

# apt-getパッケージ管理のupdateとapache2のインストール
RUN apt-get update && apt-get install -y apache2 

aptコマンドは使えませんでした。
↑ いけたけど、WARNING: apt does not have a stable CLI interface. Use with caution in scripts.が出てあんま推奨されてないっぽい。

じゃあbuildしましょう。

# リビルドするときはタグ名を後ろにつけたらおk
$ docker build -t test:latest .
・
・
・
Step 1/2 : FROM ubuntu:latest
 ---> c9d990395902
Step 2/2 : RUN apt-get update && apt-get install -y apache2
 ---> Using cache
 ---> 5a2551cf2ad8
Successfully built 5a2551cf2ad8
Successfully tagged test:latest

Apacheインスコが終了しました。

ちょっと確認

本当に入っているかどうか、コンテナの中に入って確認してみます。

$ docker run -it c9d990395902 /bin/bash
# 

これでさっきのイメージIDを元にコンテナの中に入れます。

# apache2 -v
Server version: Apache/2.4.18 (Ubuntu)
Server built:   2017-09-18T15:09:02

ちゃんとApache入ってました\(^o^)/

ここでctrl + p + qを押せばコンテナを起動したまま出ることができますが、今回はその必要もないのでexitコマンドで出ます。
exitだとコンテナ起動と終了を一緒にやってくれます。

ちなみに

直接コンテナに入ってから、apt-getで何かパッケージをインスコした場合、exitで出てしまうとそのインスコはなかったことになります。

これは、imageがbuildした際の状態を保っているからです。

なので、「あれ〜この前インスコしたのになぁ〜」ってなったときはこの可能性が多いです。
要注意です。まじで。

CMD命令

デーモン実行。
イメージを元に生成したコンテナ内でコマンドを実行するために使うやつ。

ちなみにこいつはDockerfile内で一つしかかけない。複数書いた場合は、最後のだけが実行される。

さっきのDockerfileの最後に、Apacheサーバーを立てるコマンドを記載してみます。

FROM ubuntu:latest

# apt-getパッケージ管理のupdateとapache2のインストール
RUN apt-get update && apt-get install -y apache2

# デーモン起動
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]

ここでちょっと詰まったのですが、デーモン起動の際に/usr/sbin/apache2では起動しませんでした。
要注意です。

CentOSの場合は/usr/sbin/httpdです。

コンテナを起動

docker runでポート指定(-pオプション) & デタッチド(-dオプション)で起動します。

$ docker run -d -p 80:80 test

or

$ docker run -p 80:80 -d test

長い文字列が出ると思います。
なにか問題があればメッセージが出るはず。

本当に起動してるか確認しましょー。

docker psコマンドで。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
78fe3aafeada        test                "/usr/sbin/apachectl…"   4 seconds ago       Up 3 seconds        0.0.0.0:80->80/tcp   nervous_morse

動いてなければここで表示されないです。 今回はちゃんと表示されているので問題なしです。

特定のものだけ表示したい場合はフォーマットを指定すればおk。
例えばこんな感じ。

$ docker ps --format={{.Image}} {{.Command}} {{.Ports}}

こうすれば、イメージ名と実行したコマンド、ポートが表示されます。参考程度に。

画面の確認

ポートを80 -> 80に開放しているので単純にlocalhostでアクセスできます。

f:id:rdwbocungelt5:20180416101239p:plain

問題なさげ!

終わり

次回はファイルの追加やボリュームの指定、ポートのエクスポート等を簡単なDockerfileを元に作成したいと思います。

みんなDockerfileかけるようになろう(自問自答)。

じゃーの。