仕事でDjango製のWebアプリのテスト環境をDockerで作る、という試みをやったのでその入り口になる話を書いてみる。
Docker Hubを探せばPython3.7のイメージはあるけど、ここではUbuntu16.04のイメージを使う。
Ubuntu 16.04のイメージにPython3.7をインストールする
Dockerfile中にコメントを書いている通り、Ubuntu16.04にPython3.7をインストールする方法は以下の記事を参考にした。
# 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"
以下がそのスクリプト。
# sample.py print('spam ham eggs')
マウントしたスクリプトを実行する
docker-compose build でサービスをビルドしてから、docker-compose upでサービスを実行する。
スクリプトがファイルを出力するとき
docker-compose.ymlの中でマウントすると、コンテナ上で作成されたファイルはローカルにも作られる。
このとき、ReadOnlyを外しておかないと怒られる。
# 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('醜いよりも美しい方が良い。')
これを書いて、サービスを実行するとローカルに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にコンテナ上にファイルが作られたか確認するためにファイルの中身を確認する処理を追記した。
# 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を使ったテスト環境を作れる。