あいつの日誌β

働きながら旅しています。

docker compose 入門

あらすじ

aws の ECS ってなんかすごい気がするから Docker やろうと思いました。

環境

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.10.5
BuildVersion:   14F1505

% docker-machine -v
docker-machine version 0.5.2 ( 0456b9f )

% docker -v
Docker version 1.9.1, build a34a1d5

% docker-compose -v
docker-compose version 1.5.2, build 7240ff3

準備

下記のファイルを用意します。

% mkdir ~/practice-docker-compose && cd $_
% mkdir -p compose/dataonly
% touch comopose/dataonly/Dockerfile
% mkdir -p compose/nginx/env/etc/nginx/
% touch compose/nginx/env/etc/nginx/nginx.conf
% mkdir -p compose/app
% touch Dockerfile app.js package.json
% touch docker-compose.yml

こういう構成になると思います。

% tree
.
├── compose
│   ├── app
│   │   ├── Dockerfile
│   │   ├── app.js
│   │   └── package.json
│   ├── dataonly
│   │   └── Dockerfile
│   └── nginx
│       ├── Dockerfile
│       └── env
│           └── etc
│               └── nginx
│                   └── nginx.conf
└── docker-compose.yml

create Docker Host on VirtualBox

Docker のホストを用意します。

% docker-machine create --driver virtualbox dev

すでに作成されている場合は下記で起動します

% docker-machine start dev

環境変数をセットします。

% eval $(docker-machine env dev)

dataonly container

edit compose/dataonly/Dockerfile:

FROM busybox

RUN ["mkdir", "-p", "/var/log/app"]
RUN ["mkdir", "-p", "/var/log/nginx"]

VOLUME /var/log/app
VOLUME /var/log/nginx

コンテナの Image を作成します。

% docker build -t okamuuu/myapp-dataonly compose/dataonly

先ほど生成したコンテナの Image からプロセスを起動します。 プロセスとの対話が始まりますが exit を実行してこのプロセスを終了させます。

% docker run -it --name myapp-dataonly okamuuu/myapp-dataoly
/ # exit

データ専用コンテナはプロセスとして起動させずに使用します。 もし書き込まれたデータを確認したい場合は上記コマンドでプロセスとして起動させて ls -a /var/log などを実行すれば OK です

app container

自身のホスト名を返すだけの node アプリを作成します。

edit compose/app/app.js:

var hostname = require('os').hostname();
var http = require('http');
http.createServer(function (req, res) {
  console.log(hostname);
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end("hello, I'm " + hostname);
}).listen(8080);
console.log('Server running at http://127.0.0.1:8080/');

edit compose/app/package.json:

{
  "name": "myapp",
  "version": "1.0.0",
  "description": "", 
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },  
  "keywords": [], 
  "author": "", 
  "license": "ISC"
}

edit compose/app/Dockerfile:

FROM node

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ADD package.json /usr/src/app/
RUN npm install
ADD . /usr/src/app

CMD npm start > /var/log/app/app.log

build

% docker build -t okamuuu/myapp-app compose/app 

起動

% docker run -it --name --volumes-from myapp-dataonly myapp-app okamuuu/myapp-app

確認

% curl http://$(docker-machine ip dev):8080 
hello, I'm c6d325645087

このプロセスは一旦このままにしておきます。次の nginx container の動作確認で使用します。

なお、ログを確認するには以下のコマンドで dataonly コンテナーにアタッチしてログを確認できます。

% docker start -ia myapp-dataonly
# tail -f /var/log/app/app.log

nginx container

edit compose/nginx/env/etc/nginx/nginx.conf:

worker_processes auto;

events { worker_connections 1024; }

http {
    upstream node-app {
          least_conn;
          server myapp-app1:8080 weight=10 max_fails=3 fail_timeout=30s;
          server myapp-app2:8080 weight=10 max_fails=3 fail_timeout=30s;
          server myapp-app3:8080 weight=10 max_fails=3 fail_timeout=30s;
    }
     
    server {
          listen 80;
     
          location / {
            proxy_pass http://node-app;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
          }
    }
}
% touch compose/nginx/Dockerfile

edit compose/nginx/Dockerfile

FROM nginx

ADD env/etc/nginx/nginx.conf /etc/nginx/

CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

イメージを生成します

% docker build -t okamuuu/myapp-nginx compose/nginx

起動

% docker run -it --name myapp-nginx -p 80:80 --volumes-from myapp-dataonly --link myapp-app:myapp-app1 --link myapp-app:myapp-app2 --link myapp-app:myapp-app3 okamuuu/myapp-nginx

確認

% curl http://$(docker-machine ip dev):80
hello, I'm b3ac3081baa6

確認が終わったら起動している Docker container (myapp-app と myapp-nginx)を停止します。 以下のコマンドを実行して残骸をきれいにします。

docker rm `docker ps -a -q`

docker-compose

edit docker-compose.yml

myapp-app1:
  build: compose/app
  volumes_from:
    - myapp-dataonly

myapp-app2:
  build: compose/app
  volumes_from:
    - myapp-dataonly

myapp-app3:
  build: compose/app
  volumes_from:
    - myapp-dataonly

myapp-nginx:
  build: compose/nginx
  ports:
    - "80:80"
  links:
    - myapp-app1
    - myapp-app2
    - myapp-app3
  volumes_from:
    - myapp-dataonly

先ほど myapp-dataonly のコンテナを削除していると思うのでもう一回作成します。

% docker run -it --name myapp-dataonly okamuuu/myapp-dataoly
/ # exit

起動します。

% docker-compose up

確認

% curl http://$(docker-machine ip dev):80
hello, I'm dac01a6e3de9
% curl http://$(docker-machine ip dev):80 
hello, I'm 1673c30182a6
% curl http://$(docker-machine ip dev):80
hello, I'm 66fff4bffb60
% curl http://$(docker-machine ip dev):80
hello, I'm dac01a6e3de9

Crtl-C で終了した後は以下でコンテナを綺麗にできます。

docker-compose rm

それではみなさま良いお年を