仕事でDjango製のWebアプリのテスト環境をDockerで作る、という試みをやったのでその入り口になる話を書いてみる。
Docker Hubを探せばPython3.7のイメージはあるけど、ここではUbuntu16.04のイメージを使う。
Ubuntu 16.04のイメージにPython3.7をインストールする
Dockerfile中にコメントを書いている通り、Ubuntu16.04にPython3.7をインストールする方法は以下の記事を参考にした。
medium.com
# Dockerfile
FROM ubuntu:16.04
# refs. Install Python3.7 in ubuntu 16.04
# https://medium.com/@manivannan_data/install-python3-7-in-ubuntu-16-04-dfd9b4f11e5c
RUN apt update && apt-get install -y \
build-essential \
checkinstall \
libreadline-gplv2-dev \
libncursesw5-dev \
libssl-dev \
libsqlite3-dev \
tk-dev \
libgdbm-dev \
libc6-dev \
libbz2-dev \
zlib1g-dev \
openssl \
libffi-dev \
python3-dev \
python3-setuptools \
wget \
&& mkdir /tmp/Python37
WORKDIR tmp/Python37
RUN wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz \
&& tar xvf Python-3.7.0.tar.xz
WORKDIR /tmp/Python37/Python-3.7.0
RUN ./configure --enable-optimizations \
&& make altinstall \
&& mkdir /usr/local/Python
WORKDIR /usr/local/Python
Linux力が全然無いので、Python3.7を入れるだけでこんなにパッケージが必要なのか(小並)となった。
docker-compose.ymlを書く
次にdokcer-compose.ymlを用意する。
Pythonスクリプトを置いたディレクトリをReadOnlyでマウントしてから、ファイルを実行する。
# docker-compose.yml
version: "2"
services:
python:
build: .
container_name: run_python
volumes:
- ./src:/usr/local/Python/:ro
command: "python3.7 sample.py"
以下がそのスクリプト。
print('spam ham eggs')
マウントしたスクリプトを実行する
docker-compose build
でサービスをビルドしてから、docker-compose up
でサービスを実行する。
スクリプトがファイルを出力するとき
docker-compose.yml
の中でマウントすると、コンテナ上で作成されたファイルはローカルにも作られる。
このとき、ReadOnly
を外しておかないと怒られる。
zen_en = 'zen_en.txt'
zen_ja = 'zen_ja.txt'
with open(zen_en, 'w', encoding='utf-8') as f:
f.write('Beautiful is better than ugly.')
with open(zen_ja, 'w', encoding='utf-8') as f:
f.write('醜いよりも美しい方が良い。')
これを書いて、サービスを実行するとローカルに2つのファイルが作られる。
ローカルに影響を与えたくないのであれば、Dockerfile
にCOPY
を追加する。
このとき、docker-compose.yml
からvolumes
は消しておく。
# Dockerfile
.
.
.
WORKDIR /tmp/Python37/Python-3.7.0
RUN ./configure --enable-optimizations \
&& make altinstall \
&& mkdir /usr/local/Python
WORKDIR /usr/local/Python
COPY ./src /usr/local/Python/
# docker-compose.yml
version: "2"
services:
python:
build: .
container_name: run_python
command: "python3.7 sample.py"
スクリプトに変更があったときはサービスをビルドし直してから、実行する必要があってひと手間増えてしまう(´・ω・`)
sample.py
にコンテナ上にファイルが作られたか確認するためにファイルの中身を確認する処理を追記した。
zen_en = 'zen_en.txt'
zen_ja = 'zen_ja.txt'
with open(zen_en, 'w', encoding='utf-8') as f:
f.write('Beautiful is better than ugly.')
with open(zen_ja, 'w', encoding='utf-8') as f:
f.write('醜いよりも美しい方が良い。')
with open(zen_en, encoding='utf-8') as f:
for line in f:
print(line)
with open(zen_ja, encoding='utf-8') as f:
for line in f:
print(line)
$ docker-compose build
.
.
.
$ docker-compose up
Recreating run_python ... done
Attaching to run_python
run_python | Beautiful is better than ugly.
run_python | 醜いよりも美しい方が良い。
run_python exited with code 0
まとめ
「Dockerコンテナ上にスクリプトを置いて、コマンドを実行する」という流れを応用して、「Webアプリを置いてテストコマンドを実行」とすればDockerを使ったテスト環境を作れる。