仕事で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を使ったテスト環境を作れる。