K4750.NET

DockerfileのCOPYの動きを確認してみる

DockerfileのCOPY命令がファイルの内容に変化がなければキャッシュを使うことは分るが・・・ファイルが消えた時等はどうなるのだろう・・・ということで試してみた。


1.サンプルファイル

Dockerfile
src\
   a.txt
   b.txt
   c.txt

Dockerfileの内容:

FROM alpine:latest
COPY src dst

2.初回ビルド

$ docker build -t copytest .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM alpine:latest
latest: Pulling from library/alpine
4fe2ade4980c: Already exists
Digest: sha256:621c2f39f8133acb8e64023a94dbdf0d5ca81896102b9e57c0dc184cadaf5528
Status: Downloaded newer image for alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> 7a3d51886012
Successfully built 7a3d51886012
Successfully tagged copytest:latest

COPY結果を確認してみる。

$ docker run --rm copytest ls -l /dst
total 0
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 a.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 b.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 c.txt

3.2回目ビルド

ホスト環境を何も変えず、2回目を実行してみる。

$ docker build -t copytest .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> Using cache
 ---> 7a3d51886012
Successfully built 7a3d51886012
Successfully tagged copytest:latest

COPYは実行されず、キャッシュが使われている。よって、COPY結果も変わらず。


4.ファイルを追加する

まずはファイルを追加してみる。

Dockerfile
src\
   a.txt
   b.txt
   c.txt
   d.txt <- ファイルを追加する

ビルドを実行してみると・・・

$ docker build -t copytest .
Sending build context to Docker daemon  4.608kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> 4584e2974830
Successfully built 4584e2974830
Successfully tagged copytest:latest

キャッシュは使われずに、COPYが実行されている。結果を確認してみる。

$ docker run --rm copytest ls -l /dst
total 0
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 a.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 b.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 c.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 d.txt

5.追加したファイルを削除する

先ほど追加した d.txt を削除して、ビルドを実行してみると、

$ docker build -t copytest .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> Using cache
 ---> 7a3d51886012
Successfully built 7a3d51886012
Successfully tagged copytest:latest

予想に反して(?)、(d.txtを追加する前に作成した)キャッシュが使われている。賢い^^;


6.さらにファイルを削除する

さらに c.txt を削除して、ビルドを実行してみると、

$ docker build -t copytest .
Sending build context to Docker daemon  3.584kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> c8f23fe46a11
Successfully built c8f23fe46a11
Successfully tagged copytest:latest

ファイルが消えたことを検知して、COPYが実行された。dstの内容は・・・

$ docker run --rm copytest ls -l /dst
total 0
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 a.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 b.txt

期待通りの動きだ^^

オライリーの「Docker」のサンプルが動かなかったので修正してみる

約2年前の2016年8月に発行されたオライリー「Docker」。5章「開発でのDockerの利用」を実際に手を動かして確認してみたところ、所々動かない個所があったので修正してみる。


1.「5.1 “Hello World!”」

コンテナ内で実行してみたがエラーになる・・・どうやら2行目がインデントされているのが問題のようだ。

from flask import Flask
    app = Flask(__name__) 

@app.route('/') 
def hello_world():
    return 'Hello World!\n'

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

下記 Dockerfile は問題なし。

FROM python:3.4
RUN pip install Flask==0.10.1
WORKDIR /app
COPY app /app
CMD ["python", "identidock.py"]

コンテナのビルド&起動も問題なし。

$ docker build -t identidock .
$ docker run -d -p 5000:5000 identidock

curlコマンドによる動作確認は・・・Windows環境なのでcurlがないのと、コンテナ内へホスト環境からアクセスするには上記Pythonコードの「host=0.0.0.0」をコンテナに割り当てられたIPアドレスに書き換える必要(?)があるようなので・・・せっかくなのでcurlがインストールされたDockerイメージを使って動作確認してみる。

$ docker run --rm -it --entrypoint /bin/sh byrnedo/alpine-curl
/ # curl http://172.17.0.3:5000/
Hello World!

IPアドレス「172.17.0.3」は、identidockイメージから起動されたコンテナのアドレス。本来ならば –link 等を使ってもっとエレガントにやるのだろうが・・・。続いて、アプリケーションサーバ uWSGI を使うためのDockerfile。

FROM python:3.4
RUN pip install Flask==0.10.1 uWSGI==2.0.8
WORKDIR /app
COPY app /app
CMD ["uwsgi", "--http", "0.0.0.0:9090", "--wsgi-file", "/app/identidock.py", \
     "--callable", "app", "--stats", "0.0.0.0:9191"]

uWSGIのコンパイル(?)エラーが出力されて、イメージのビルドに失敗する。。Pythonのバージョンを変えたり、FlaskやuWSGIのバージョン指定を外したりしても改善しなかったので、結局UbuntuをベースにPython3.6をインストールするやり方にしてみた。

FROM ubuntu:18.04
RUN apt-get update -y && apt-get install -yq python3-pip python3-dev wget && \
    wget https://bootstrap.pypa.io/get-pip.py && python3.6 get-pip.py && \
    pip install Flask uWSGI
WORKDIR /app
COPY app /app
CMD ["uwsgi", "--http", "0.0.0.0:9090", "--wsgi-file", "/app/identidock.py", "--callable", "app"]

CMD行も”–stats”あたりでエラーが出てコンテナが起動できなかったので、パラメタを削除して起動するようにした。

Angular7 in Docker

Docker for Windows(Docker Community Edition for Windows)をWindows 10 PCへインストールしたので、試しにAngular7をコンテナ内でビルドし、実行してみます。


1.Dockerfile を書いてみる

Node.jsがインストール済みのイメージファイルをベースにして、Angular CLIのインストールと新規プロジェクトの作成をすればよいので・・・こんな感じかな?

FROM node:10-alpine
WORKDIR /work
RUN npm install -g @angular/cli@7.0.3
RUN ng new --defaults angular7
WORKDIR /work/angular7
CMD ng serve

2.ビルド&実行

作った Dockerfile を使って ng new まで実行したイメージファイルを作り、実行してみる。

$ docker build -t angular7 .
$ docker run -p 4200:4200 --name angular7 angular7

上手くいったようだが・・・http://locahost:4200 を叩いてもアクセスできず。結局、いろいろ試したところ、DockerfileのCMD行を

CMD ng serve --host `hostname`

へ変更して再度ビルド&実行すると、ホストPC上のブラウザからは http://127.0.0.1:4200 でアクセスできることが判明。Docker for Windows 固有の問題なのだろうか・・・?とりあえず動いたから良しとしよう^^;


3.Yarn 発見

ふと気づいたのだが・・・

$ docker exec -i -t angular7 /bin/sh
/work/angular7 # yarn -v
1.10.1
/work/angular7 # which yarn
/usr/local/bin/yarn

Ultra Fastを謳う^^; Yarnコマンド(現時点の最新Stable版)が/usr/local/binにインストールされていた。早速、Dockerfileを書き換えてみる。

FROM node:10-alpine
WORKDIR /work
RUN yarn global add @angular/cli@7.0.3
RUN ng new --defaults --skipInstall=true angular7
WORKDIR /work/angular7
RUN yarn
CMD ng serve --host `hostname`

こんな使い方では速度を体感することもなく・・・動いたので良しとしよう^^;;