環境構築のためのDocker

はじめに

これはMuroran Institute of Technology Advent Calendar 2018 - Adventarの記事です.

  • ホストマシンのOSはWindowsmacOSを使いたい.
  • Linuxも使いたい.(GUIは必要ない.)
  • ホストマシンの環境をできるだけ変更したくない.
  • 同じ開発環境を再現できるようにしたい.
  • できれば賢い誰かが構築した環境を利用したい.

そんな時,ホストマシンにDockerをインストールしておくと,

  • CUIだけの軽量なLinux仮想環境を構築できる.
  • 環境構築の手順はテキストファイルに記述できる.
  • そのファイルから開発環境を自動的に構築できる.
  • Docker Hubにアップロードされた環境を利用できる.

なんて,素晴らしい.

インストール

それぞれのOSにおけるDockerのインストール方法を以下に示します.

Windows 10 64bit : Pro, Enterprise or Education

Install Docker Desktop for Windows | Docker Documentation

それ以外のWindows

Install Docker Toolbox on Windows | Docker Documentation

macOS

Install Docker Desktop for Mac | Docker Documentation

Ubuntu

sudo apt install docker
sudo apt install docker-compose

Docker

Dockerはイメージをもとにコンテナを生成し,コンテナ内の環境でアプリケーションを実行します. イメージはアプリケーションとその実行環境の情報をまとめたもので,Docker Hubからpullしてきたり,Dockerfileから作成したりすることで用意します. コンテナはイメージを実体化したもので,実行中のアプリケーションの状態を保持します. Docker Hubは利用可能なイメージが集まったDockerのサービスです. Dockerfileはイメージを作成する手順を記述したテキストファイルです.

Docker Hubからpullしてきたり,Dockerfileから作成したりしたイメージは,ダウンロードしてきたり,ソースコードからビルドしたりしてSSDに保存したプログラムに例えることができると思います. また,イメージをもとに実体化され,実行されるコンテナは,SSDからメモリにロードされ実行されるプログラムに例えることができると思います.

dockerのコマンド

  • docker --help : dockerのヘルプを表示する.
  • docker build -t イメージ名 ディレクトリ : 指定されたディレクトリのDockerfileから指定されたイメージ名のイメージを作成する.
  • docker run イメージ [コマンド] : 指定されたイメージを基にコンテナを起動し,コンテナ内で指定されたコマンドを実行する.
  • docker stop コンテナ : 指定された実行中のコンテナを停止する.
  • docker ps : 実行中のコンテナ一覧を表示する.
  • docker images : ホストマシンにあるイメージ一覧を表示する.
  • docker rm コンテナID : 指定されたコンテナIDを持つコンテナを削除する.
  • docker rmi イメージID : 指定されたイメージIDを持つイメージを削除する.

Dockerfile

Dockerfileはイメージを作成する手順を記述したテキストファイルで,以下のように記述します.

# 基にするイメージを指定する.Docker Hubから探してくることが多い.
FROM ベースイメージ

# 作業ディレクトリを指定する.
WORKDIR /workdir/path

# ホストマシンのファイルやディレクトリをコンテナ内に複製する.
COPY host/path/ container/path

# Shellコマンドを実行する.アプリケーション実行のための準備を行う.
RUN shell command

# コンテナ実行時に実行されるアプリケーション実行コマンドを指定する.
CMD ["アプリケーション実行コマンド", "コマンドライン引数1", "コマンドライン引数2", ...]

使用例

Hello World

次のコマンドを実行すると,

docker run hello-world

dockerはホストマシンに保存されているhello-worldイメージからコンテナを生成し,Hello Worldを出力するアプリケーションをコンテナ内で実行します. ホストマシンにhello-worldイメージがないときは,dockerはDocker Hubからhello-worldイメージをpullしてきてホストマシンに保存します.

Bash

次のコマンドを実行すると,

docker run -i -t ubuntu bash

dockerはホストマシンに保存されているubuntuイメージから(無いときはDocker Hubからpullして保存する.)コンテナを生成し,コンテナ内でBashを実行します. -i, -tオプションはホストマシンのの標準入出力とコンテナの標準入出力を繋いぐためのオプションです.

C++

次の内容のファイルを用意します.

  • ./Dockerfile
FROM ubuntu
WORKDIR /home/app
COPY ./src/main.cpp /home/app
RUN apt update -y && apt upgrade -y && apt install -y g++
RUN g++ -o main main.cpp
CMD ["./main"]
  • ./src/main.cpp
#include<iostream>

int main(int argc, char *argv[])
{
    std::cout << "hello docker-cpp" << std::endl;
}

次のコマンドを実行すると,

docker build -t docker-cpp ./

カレントディレクトリのDockerfileからdocker-cppという名前のイメージが作成されホストマシンに保存されます. docker-cppは具体的にはDockerfileに従い以下のように作成されます.

  1. ubuntuのイメージをダウンロードする.
  2. 作業ディレクトリを/home/appに設定する.
  3. apt update -y && apt upgrade -y && apt install -y g++を実行し,アプリケーションのビルドの準備をする.
  4. g++ -o main main.cppを実行し,アプリケーションをビルドする.
  5. コンテナ起動時に./mainというコマンドでアプリケーションを実行するように設定する.

イメージ作成後に次のコマンドを実行すると,

docker run docker-cpp

ホストマシンに保存されたdocker-cppという名前のイメージからコンテナが生成された後に./mainが実行されて次の実行結果が得られます.

hello docker-cpp

Docker Compose

Docker Composeはdocker-compose.ymlに記述された設定に従って,1つ以上のコンテナを連携させて起動するものです. docker-compose.ymlはコンテナ起動時の設定を記述するテキストファイルです.

docker-composeのコマンド

  • docker-compose --help : docker-composeのヘルプを表示する.
  • docker-compose build : docker-compose.ymlに従ってイメージを作成し,保存する.
  • docker-compose up [-d] : docker-compose.ymlに従ってコンテナを起動する.-dオプションを付けるとコンテナをバックグラウンドで実行する.
  • docker-compose run コンテナ名 コマンド : コンテナ名を持つコンテナを起動し,コンテナ内でアプリケーションの代わりにコマンドを実行する.
  • docker-compose exec コンテナ名 コマンド : コンテナ名を持つ起動中のコンテナ内でコマンドを実行する.
  • docker-compose stop : 起動したコンテナを停止する.

docker-compose.yml

# docker-compose.ymlのバージョンを指定する.'3'を指定する.
version: '3'

# コンテナごとの設定を記述する.
services: 
  コンテナ名:

    # コンテナの名前をコンテナ名に設定する.
    container_name: 'コンテナ名'

    # imageまたはbuildでコンテナのイメージを指定する.
    # イメージを直接指定するときはimageで指定する.
    image: 'イメージ'
    # イメージをDockerfileで指定するときはbuildで指定する.
    build:
      # Dockerfileがあるディレクトリを指定する.
      context: 'Dockerfileのディレクトリ'
      # Dockerfileのファイル名を指定する.
      dockerfile: 'Dockerfile名'

    # ホストマシンのディレクトリをコンテナにマウントする.
    volumes: 
      - 'ホストマシンのディレクトリ:コンテナのディレクトリ'

    # ホストマシンのポートを開放し,コンテナのポートに接続する.
    ports: 
      - 'ホストマシンの開放ポート:コンテナの開放ポート'

    # コンテナ起動時に実行されるコマンドを指定する.
    command: ["コマンド", "コマンドライン引数1", ... ]

使用例

Python

次のファイルを用意します.

  • ./docker-compose.yml
version: '3'

services: 
  docker-py:
    container_name: 'docker-py'
    image: 'python:3'
    working_dir: '/home/app'    
    volumes: 
      - './app:/home/app'
    command: ["python", "main.py"]
  • ./app/server.py
print("hello docker-py")

次のコマンドを実行すると,

docker-compose up

カレントディレクトリのdocker-compose.ymlの設定に従って,docker-pyという名前のコンテナが起動し,次の実行結果が得られます.

hello docker-py

docker-pyは具体的にはdocker-compose.ymlに従い以下のように起動されます.

  1. python:3のイメージをダウンロードする.
  2. 作業ディレクトリを/home/appにする.
  3. ホストマシンの./appをコンテナの/home/appにマウントする.
  4. コンテナを起動してpython main.pyを実行する.

また,次のコマンドを実行して,

docker-compose run docker-py bash

コンテナ内でpythonを実行するとPythonが対話モードで起動します.

Gnuplot

次のファイルを用意します.

  • ./Dockerfile
FROM ubuntu

WORKDIR /home/files
COPY ./files /home/files
RUN apt update -y && apt upgrade -y && apt install -y gnuplot

CMD ["gnuplot", "plot-cos.plt"]
  • ./docker-compose.yml
version: '3'

services: 
  gnuplot:
    build: 
      context: './'
      dockerfile: 'Dockerfile'
    container_name: 'gnuplot'
    volumes: 
      - './files:/home/files/'
  • ./files/plot-cos.plt
set terminal pdfcairo
set output 'plot-cos.pdf'
set xrange [-2*pi:2*pi]
set yrange [-1.5:1.5]
set samples 500
plot cos(x)
  • ./files/plot-sinc.plt
set terminal pdfcairo
set output 'plot-sinc.pdf'
set xrange [-10*pi:10*pi]
set yrange [-1:1.2]
set samples 500
plot sin(x)/x

次のコマンドを実行すると./files/plot-cos.pdfが生成されます.

docker-compose build
docker-compose up

次のコマンドを実行して,

docker-compose build
docker-compose run gnuplot bash

コンテナ内でgnuplot ./plot-sinc.pltを実行すると./files/plot-sinc.pdfが生成されます.

PHP

次のファイルを用意します.

  • ./docker-compose.yml
version: '3'

services: 
  docker-php:
    container_name: 'docker-php'
    image: 'php:7.2-apache'
    volumes: 
      - './html:/var/www/html'
    ports: 
      - '8080:80'
  • ./html/index.php
<?php
echo "hello docker-php"
?>

次のコマンドを実行して,

docker-compose up -d

ブラウザでhttp://localhost:8080にアクセスするとhello docker-phpと表示されます.

まとめ

  • DockerとDocker Composeを利用すると,ホストマシンのOSに依らずに,再現性のある軽量な仮想Linux環境を自動的に構築できます.
  • Dockerはイメージからコンテナを実体化し,アプリケーションを実行します.
  • Docker Composeはdocker-compose.ymlの設定に従ってコンテナを起動します.
  • Dockerfileにはイメージの作成手順を書き,docker-compose.ymlにはコンテナ起動時の設定を書きます.