Dockerを使ってみる 中編 ~Dockerfile~ djangoで使うことを想定
概要
とにかくdockerを使ってみる。今回は、dockerfile編。herokuで使うときも重要になってくる。
参考書籍
プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化
- 作者: 阿佐志保,山田祥寛
- 出版社/メーカー: 翔泳社
- 発売日: 2015/11/20
- メディア: 大型本
- この商品を含むブログ (3件) を見る
やってみたこと
Dockerfileについて
Dockerfileは、dockerのインフラ構成を記述したファイルのこと。
localでcontainerの設定するときは、Docker Containerを生成、Docker Container内で、apt-getなどのinstallを手動でやる必要がある。そうして出来上がったコンテナで構築した状態を元にDocker イメージを生成するという手順。
書籍より引用 ベースになるDockerイメージ Dockerコンテナ内で行った操作(コマンド) 環境変数などの設定 Docker コンテナ内で動作させておくデーモン実行
Dockerfileは、Docker場で動作させるコンテナの構成情報を記述しておくためのファイル。DockerはDockerfileを元にしてコンテナの元になるイメージを作成する。 docker build コマンドで、Docker imageを作成する。
Dockerfileの基本構成・作成
Docker コンテナをどのDockerイメージから生成するのか
FROM イメージ名
イメージ名を特定したい場合は、ダイジェストを指定する。
FROM [イメージ名]@[ダイジェスト] # ダイジェストの確認方法 $ docker images --digests イメージ名
Dockerfileの作成者を記述する。
MAINTAINER [名前やメールアドレス]
DockerfileからDockerイメージを作成してみる
docker build -t [作成するイメージ名]:[タグ名] [Dockerfileの場所]
具体的には以下のような手順になる。
- まず、Dockerfileを作成する、Dockerfileには
FROM centos:centos7
とか入れておく docker build -t buildtest:1.0 /Users/test/sampledocker
絶対パスにしてあるが、相対パスも可。
docker imageが出来上がった!
ちょっと混同しやすいと思ったのが、imageとcontainerの違い。これは注意しないと。
標準入力からのビルドも可能。 標準入力・出力については全く知らなかったけど、以下のサイトで何となく分かりました。
$ docker build - < Dockerfile # ただ標準入力では、ADD命令などが使えないため、tarでまとめてから標準入力をする $ docker build - < docker.tar.gz
Docker イメージのレイヤー構造
Dockerfileのサンプル。以下のような感じで、イメージは
FROM centos:latest <- 1つ目のイメージを作成 RUN yum install -y httpd <- 2つ目のイメージを作成 COPY index.html /var/www/html/ <- 3つ目のイメージを作成 CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"] <- 4つ目のイメージを作成
コマンド/デーモンの実行
RUN [コマンド] # shell形式 RUN yum -y install httpd RUN echo これはshell形式 # exec形式 RUN ["/bin/bash", "-c", "yum -y install httpd"] RUN ["echo", "これはexec形式"] RUN ["/bin/bash", "-c", "echo 'こちらはexec形式'"] # RUN命令を複数指定する場合(この場合、4つのイメージレイヤーが作られる RUN yum -y install httpd RUN yum -y install php RUN yum -y install php-mbstring RUN yum -y install php-pear # RUN命令を1行で指定する場合(この場合、1つのイメージレイヤー RUN yum -y install httpd php php-mbstring php-pear # \ バックスラッシュで可読性をあげる RUN yum -y install \ httpd \ php \ php-mbstring \ php-pear
デーモンの実行
- RUN -> イメージを作成するために実行する
- CMD -> イメージを元に生成したコンテナ内でコマンドを実行する
- Dockerfileには、1つのCMDを記述することができる。複数指定した場合は、最後のコマンドのみ有効となる。
- apacheを例にとると、
RUN yum-y install httpd
でhttpdをinstallして、CMD /usr/sbin/httpd -D FOREGROUND
でイメージを元に作成したコンテナ内で、常時Webサーバを起動させた状態にする。 - exec形式の場合は、
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
となる。
Dockerfile例
FROM centos:centos7 RUN yum install -y httpd CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
docker buildで、imageを生成してみる。
docker build -t sample .
ただし、これはあくまでも、imageの生成で、コンテナの生成ではないので、注意!ここが自分的には混同しやすい。imageの生成とコンテナの生成・起動は全く別のステップとして認識する。
上記のイメージで、コンテナを生成・起動すると、自動でhttpdが起動するというイメージ!あくまでもDockerfileから生成されるのは、image!image生成後に、コンテナの生成・起動が必要。
docker run -d -p 80:80 sample
これで初めて、コンテナが起動して、sampleという名前のイメージが起動する。-p(port)は、コンテナのport80を、ホストの80に繋いでいるという意味。
ENTORYPOINT命令
ENTORYPOINT -> docker run コマンドでコンテナを起動した時に、実行されるコマンド (CMDとの使い方の違いはまだよくわかってない。)
# httpdの実行 shell ENTORYPOINT /usr/sbin/httpd -D FOREGROUND # httpdの実行 exec ENTORYPOINT ["/usr/sbin/httpd", "-D", "FOREGROUND"]
ENTORYPOINTとCMDの違い
docker run コマンド(コンテナの起動・生成)の時の動作が違う。
- CMD -> docker run で新たなコマンドを入れた場合は、そちらを優先して処理する(処理を上書きできる)
- ENTORYPOINT -> docker run のコマンドよりも、ENTORYPOINTの処理を優先する。
例えば、
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"] を記載したDockerfileのイメージを元にコンテナを起動して、 $ docker run -d -p 80:80 sample とコマンドを入力すると、httpdが起動する。 ただ、 $ docker run -d -p 81:80 sample /user/sbin/nginx -g "daemon off;" というコマンドを打つと、nginxを優先して起動する。 これを、 ENTORYPOINT ["/usr/sbin/httpd", "-D", "FOREGROUND"] に変更すると、 $ docker run -d -p 81:80 sample /user/sbin/nginx -g "daemon off;" とうっても、httpdを起動するように指定しているので、nginxの起動は無効になる。
コンテナ実行時にコマンド引数を任意に指定したい時
Dockerfile
FROM centos:latest ENTORYPOINT["top"] CMD ["-d", "10"]
ターミナルで以下のように動作を確認できる。
$ docker run -it sample <- DockerfileのCMDで指定した10秒ごとに更新する $ docker run -it sample -d 2 <- 2秒ごとに更新する
ビルド完了後に実行される命令(ONBUILD)
これはちょっとややこしいけど、イメージを重ねる時の肝になりそうな予感
Dockerfile1
FROM centos ONBUILD RUN echo "Hello world"
Dockerfile1を元にイメージをビルドする。
docker build -t basesample .
この時点では、basesample image は、hello woldを表示しない。ONBUILDは、basesample imageを元に、buildした時に、発動する。
Dockerfile2
FROM basesample
このDockerfile2を元にイメージを作成した時に、echo "Hello world"が実行されるようになる。
docker build -t productsample .
productsample image をdocker runするとecho "Hello world"が実行される。
実際のONBUILDの使い方の例
まず、ベースイメージを作成する。
Dockerfile(baseimage)->webシステムの実行環境のイメージ
# Dcoker イメージの取得 FROM centos:latest # Apache httpdのインストール RUN ["yum", "-y", "install", "httpd"] # Webコンテンツの配置 # このイメージを元に、buildする時に、website.tar をコンテナ内の/var/www/html/に追加するという指示 ONBUILD ADD website.tar /var/www/html/ # httpdの実行 CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
このDockerfileの名前を、Dockerfile.baseという名前にする。 その場合、次のコマンドでイメージをビルドする。
# Dockerfile.baseを元に、web-baseという名前のイメージをビルド(作成)する。 $ docker build -t web-base -f Dockerfile.base .
web-baseを元に作成したコンテナでは、add website.tarは実行されない。このweb-baseを元に作成したイメージで起動したコンテナで、add website.tarが実行される。
website.tarを作成
とりあえず、仮のファイルとしてwebsite.tarを適当に作ってみる。
$ touch website.tar
Webサーバ用のイメージの作成
Dockerfileを作成
# Docker.baseを元にbuildしたweb-base imageを指定する FROM web-base
Dockerfileとwebsite.tarは同じフォルダに入れておく
$ ls Dockerfile Dockerfile.base website.tar
Dockerfileを元にbuildしてみる。
$ docker build -t web-image .
無事buildできた!
webサーバ用コンテナの起動
# web-imageというイメージをもとに、ホストの80をコンテナの80をつなげてコンテナを起動・生成する。 $ docker run -d -p 80:80 web-image
多分、これでbaseと、アプリのデプロイの環境を分けることができる。
環境・ネットワークの設定
環境変数の設定(ENV命令)
2種類ある。
# ENV [キー名] [値] -> 複数のイメージが作られる ENV myName "Djangoroid" ENV myNumber = "1234567" # ENV [キー名]=[値] -> 1つのイメージにまとめられる ENV myName = "Djangoroid" \ myNumber = "1234567" \
作業ディレクトリの指定(WORKDIR)
cd と似たようなコマンドになる。
WORKDIR /test WORKDIR admin # ENVで指定する場合(環境変数を使う場合は、$を先頭につける) ENV DIRPATH /test ENV DIRNAME admin WORKDIR $DIRPATH/$DIRNAME RUN ["pwd"]
ユーザーの指定
RUN ["adduser","test"] RUN ["whoami"] <- root USER test RUN ["whoami"] <- test
ラベルの指定(LABEL)
LABEL-> イメージにバージョン情報、コメント情報を持たせるとき
LABEL title="testimage" LABEL version="2.0"
ポートの設定(EXPOSE)
# EXPOSE ホスト側のポート番号 EXPOSE 8080(<- ここはホスト側のポート)
ファイルシステムの設定
ファイル・ディレクトリの追加(ADD)
# ADD ホストPCのファイルパス Dockerイメージのファイルパス ADD index.html /test_dir/ <-hostPCのindex.htmlを、Dockerイメージのtest_dirにコピーする。 # ADD ["ホストPCのファイルパス", "Dockerイメージのファイルパス"] # 追加するファイルがリモートファイルURLの場合(ただし、ファイルはパーミッション600(ユーザーのみが読み書き可能)になるため注意) ADD http://pythonskywalker.hatenablog.com/index.html /docker_dir/ # 認証が必要な場合は、RUN wget, curlを使う # URLからファイルをダウンロードして、指定したファイル名を追加する
ビルドで除外したいファイルには、.dockerignoreファイルを使う
$ cat .dockerignore Dummyfile #Dummyfileという名前のファイルを書いておく。
Dockerfileに以下のように記載してimageをビルドして、.dockerignoreに記載されているので、dummyfileは、ADDされない。
FROM centos:latest ADD dummyfile /tmp/dummyfile
ファイルのコピー(COPY)
ADD = リモートファイルのダウンロード、アーカイブの解凍などの機能がある COPY = 単純にコピーするだけ。そのため、イメージ内にファイルを配置したいだけの時は、COPY
Dockerfileの格納場所
Docker用のディレクトリを作成して、そこにDockerfileを置いてビルドするのがオススメ。不要なファイルをビルドしないように。
ボリュームのマウント(VOLUME)
web-container -> log-container を生成するときに、VOLUMEで、logの場所を指定することができる。
# web-image FROM centos # httpdのインストール RUN yum install httpd # log-image FROM centos # ボリュームの指定 VOLUME /var/log/httpd
実際に作ってみると、
Dockerfile(log-image用)
FROM centos:latest RUN ["mkdir", "/var/log/httpd"] VOLUME /var/log/httpd
log-imageをbuildしてみる。
$ docker build -t log-image .
log-imageをもとに、コンテナの起動・生成
$ docker run -it --name log-container log-image
webサーバ用のimageのDockerfileの作成
FROM centos:latest RUN ["yum", "-y", "install", "httpd"] CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
webサーバ用のimageのビルド
$ docker build -t web-image .
webサーバ用コンテナの起動
$ docker run -d --name web-container \ > -p 80:80 \ > --volumes-from log-container web-image
- --volumes-from [コンテナ名]で、指定する。
ログの確認
$ docker start -ia log-container [root@ec2a2833b6c5 /]# ls -l /var/log/httpd total 12 -rw-r--r-- 1 root root 4404 Oct 31 22:31 access_log -rw-r--r-- 1 root root 1515 Oct 31 22:30 error_log