docker-compose up で Django + PostgreSQL + Nginx + Gunicorn  を起動してみる


## 目的

boot2docker で動作するか簡単に試してみる

## インストール

下記はインストール済みの前提で

- python2.7
- Django1.8.2
- boot2docker v1.6.2
- docker-compose 1.2.0
- VirtualBOX 4.3.28

(MacOSX10.9)


## Django プロジェクト作成

```
$ django-admin startproject core
$ mv core example-django-gunicorn-nginx
$ cd example-django-gunicorn-nginx
$ tree
.
├── core
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
```

## db 設定を書き換える

```core/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
    }
}
```

## Docker 関係のファイルを追加

ディレクトリ作成

```
$ mkdir boot2docker
```

### ディレクトリ構成

```
.
├── boot2docker
│   ├── containers
│   │   ├── django
│   │   │   ├── Dockerfile
│   │   │   └── requirements.txt
│   │   └── nginx
│   │       └── nginx.conf
│   └── docker-compose.yml
```

containers ディレクトリ構成は [この記事](http://qiita.com/k-shogo/items/3c887cbf86b3cab85b72) を参考にした。


### docker-compose.yml

```boot2docker/docker-compose.yml
db:
  image: postgres
django:
  build: containers/django
  command: gunicorn core.wsgi -b 0.0.0.0:9000
  volumes:
    - ../:/app
  links:
    - db
nginx:
    image: nginx
    ports:
        - "8000:80"
    links:
        - django:django
    volumes: 
        - "containers/nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
```

### Django コンテナ

```boot2docker/containers/django/Dockerfile
FROM python:2.7
ENV PYTHONUNBUFFERED 1
ADD . /app/
WORKDIR /app
RUN pip install -r requirements.txt
```

```boot2docker/containers/django/requirements.txt
Django==1.8.2
psycopg2==2.6
gunicorn==19.3.0
```

NOTE: requirements.txt を上の階層に置きたいけど、dockerfile が上の階層のファイルを読み込めないみたい。なんとかならないかなこれ。

### Nginx コンテナ

[Nginx ドキュメントのサンプル](http://gunicorn-docs.readthedocs.org/en/latest/deploy.html) の upstream app_server 部分を変えただけ。

```
worker_processes 1;

user nobody nogroup;
pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;

events {
    worker_connections 1024;
    accept_mutex off;
}

http {
    include mime.types;
    default_type application/octet-stream;
    access_log /tmp/nginx.access.log combined;
    sendfile on;

    upstream app_server {
        server django:9000 fail_timeout=0;
    }

    server {
        listen 80 default;
        client_max_body_size 4G;
        server_name _;

        keepalive_timeout 5;

        # path for static files
        root /path/to/app/current/public;

        location / {
            # checks for static file, if not found proxy to app
            try_files $uri @proxy_to_app;
        }

        location @proxy_to_app {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;

            proxy_pass   http://app_server;
        }

        error_page 500 502 503 504 /500.html;
        location = /500.html {
            root /path/to/app/current/public;
        }
    }
}
```

### PostgreSQL コンテナ

設定などいじっていないので省略


## 実行

```
$ boot2docker init && boot2docker start && $(boot2docker shellinit)
$ docker-compose up

...

Recreating boot2docker_db_1...
Recreating boot2docker_django_1...
Recreating boot2docker_nginx_1...
Attaching to boot2docker_db_1, boot2docker_django_1, boot2docker_nginx_1
db_1     | LOG:  database system was shut down at 2015-06-06 08:16:56 UTC
db_1     | LOG:  database system is ready to accept connections
db_1     | LOG:  autovacuum launcher started
django_1 | [2015-06-06 08:17:01 +0000] [1] [INFO] Starting gunicorn 19.3.0
django_1 | [2015-06-06 08:17:01 +0000] [1] [INFO] Listening at: http://0.0.0.0:9000 (1)
django_1 | [2015-06-06 08:17:01 +0000] [1] [INFO] Using worker: sync
django_1 | [2015-06-06 08:17:01 +0000] [9] [INFO] Booting worker with pid: 9
```

```
$ boot2docker ip
<boot2docker ip>
```

web ブラウザでアクセス

- `http://<boot2docker ip>:8000`


![スクリーンショット 2015-06-06 16.51.18.png](https://qiita-image-store.s3.amazonaws.com/0/41656/74f0c6c2-b1e1-17d8-d31e-f03f290debcd.png "スクリーンショット 2015-06-06 16.51.18.png")


## 感想

- docker-compose.yml の ports と links の書き方でちょっとハマった。
- nginx の設定とか gunicorn の使い方を理解してなかったから手間取った。
- 何度もやり直ししてると boot2docker の挙動がおかしくなるっぽい。その度に boot2docker destroy やってたら時間かかった。
- 手を動かさないと理解できない性分っぽい。


## 参考

- https://docs.docker.com/compose/
- https://docs.docker.com/compose/yml/
- http://fight-tsk.blogspot.jp/2015/03/docker-composeyml.html
- https://www.djangoproject.com/
- http://qiita.com/k-shogo/items/3c887cbf86b3cab85b72
- https://github.com/dockerfile/nginx/blob/master/Dockerfile
- https://github.com/domasx2/django-angular-docker-seed
- http://gunicorn-docs.readthedocs.org/en/latest/index.html