I'm getting exasperated with deploying my nginx/django/redis/postgres setup to ECS. I have a docker-compse setup that is working perfectly in development on my local machine. However, the containers in ECS immediately stop after starting the task. I would be so happy to find out what I'm doing wrong here. I assume it is the nginx config, but don't know. See my setup:
Dockerfiles
- web
FROM python:3
ENV PYTHONUNBUFFERED 1
# Initialize
RUN mkdir -p /data/web
WORKDIR /data/web
COPY requirements.txt /data/web/
# Setup
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
# Prepare
COPY . /data/web/
EXPOSE 8000
- nginx
FROM nginx
RUN apt-get update && apt-get install openssl -y
RUN mkdir -p /etc/letsencrypt/archive/mydomain.org/
RUN mkdir -p /etc/letsencrypt/live/mydomain.org/
COPY letsencrypt /etc/letsencrypt/archive/mydomain.org/
RUN ln -s /etc/letsencrypt/archive/mydomain.org/cert1.pem /etc/letsencrypt/live/mydomain.org/cert.pem
RUN ln -s /etc/letsencrypt/archive/mydomain.org/chain1.pem /etc/letsencrypt/live/mydomain.org/chain.pem
RUN ln -s /etc/letsencrypt/archive/mydomain.org/fullchain1.pem /etc/letsencrypt/live/mydomain.org/fullchain.pem
RUN ln -s /etc/letsencrypt/archive/mydomain.org/privkey1.pem /etc/letsencrypt/live/mydomain.org/privkey.pem
RUN rm /etc/nginx/conf.d/default.conf
COPY conf /etc/nginx/conf.d/
redis and postgres come from offical images.
This is my docker-compose.yml file:
version: '2'
services:
web:
restart: always
build: ./web/
links:
- postgres:postgres
- redis:redis
env_file:
- db.env
- web_prod.env
command: gunicorn turtle.wsgi:application -w 2 -b :8000
volumes:
- /data/web
depends_on:
- postgres
- redis
nginx:
restart: always
build: ./nginx_prod/
ports:
- "80:80"
- "443:443"
volumes_from:
- web
volumes:
- /var/log/nginx
links:
- web:web
postgres:
restart: always
image: postgres:latest
volumes:
- /var/lib/postgresql/data
env_file:
- db.env
expose:
- "5432"
redis:
restart: always
image: redis:latest
expose:
- "6379"
Thereby, I load some variables to share DB credentials and set some django setting values like DEBUG=0, SECRET_KEY etc.
This is my nginx config:
worker_processes 1;
pid /tmp/nginx.pid;
error_log /var/log/nginx/error.log;
events {
worker_connections 1024;
accept_mutex off;
}
http {
include mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
sendfile on;
upstream web {
server web:8000 fail_timeout=0;
}
server {
listen 80 default_server;
return 444;
}
server {
listen 80;
charset utf-8;
server_name mydomain.org www.mydomain.org;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name mydomain.org www.mydomain.org;
keepalive_timeout 5;
location / {
try_files %uri @proxy_to_app;
}
location @proxy_to_app {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $host;
proxy_redirect off;
proxy_pass http://web;
}
ssl_certificate /etc/letsencrypt/live/mydomain.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.org/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM:EECDH:EDH:!MD5:!RC4:!LOW:!MEDIUM:!CAMELLIA:!ECDSA:!DES:!DSS:!3DES:!NULL;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/letsencrypt/archive/mydomain.org/dhparam4096.pem;
ssl_ecdh_curve secp384r1;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_stapling on;
ssl_trusted_certificate /etc/letsencrypt/live/mydomain.org/chain.pem;
ssl_stapling_verify on;
ssl_session_timeout 10m;
ssl_session_cache off;
ssl_session_tickets on;
ssl_session_ticket_key /etc/letsencrypt/archive/mydomain.org/nginx_ticketkey;
}
}
Web container is crushing with following error message.
{"log":"[2017-08-29 17:16:59 +0000] [1] [INFO] Starting gunicorn 19.7.1\n","stream":"stderr","time":"2017-08-29T17:16:59.198605099Z"}
{"log":"[2017-08-29 17:16:59 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)\n","stream":"stderr","time":"2017-08-29T17:16:59.199346576Z"}
{"log":"[2017-08-29 17:16:59 +0000] [1] [INFO] Using worker: sync\n","stream":"stderr","time":"2017-08-29T17:16:59.199357527Z"}
{"log":"[2017-08-29 17:16:59 +0000] [7] [INFO] Booting worker with pid: 7\n","stream":"stderr","time":"2017-08-29T17:16:59.202010346Z"}
{"log":"[2017-08-29 17:16:59 +0000] [8] [INFO] Booting worker with pid: 8\n","stream":"stderr","time":"2017-08-29T17:16:59.227037442Z"}
{"log":"[2017-08-29 17:16:59 +0000] [7] [ERROR] Exception in worker process\n","stream":"stderr","time":"2017-08-29T17:16:59.460028625Z"}
{"log":"Traceback (most recent call last):\n","stream":"stderr","time":"2017-08-29T17:16:59.460048425Z"}
{"log":" File \"/usr/local/lib/python3.6/site-packages/gunicorn/arbiter.py\", line 578, in spawn_worker\n","stream":"stderr","time":"2017-08-29T17:16:59.460051755Z"}
{"log":" worker.init_process()\n","stream":"stderr","time":"2017-08-29T17:16:59.460054822Z"}
{"log":" File \"/usr/local/lib/python3.6/site-packages/gunicorn/workers/base.py\", line 126, in init_process\n","stream":"stderr","time":"2017-08-29T17:16:59.460057228Z"}
{"log":" self.load_wsgi()\n","stream":"stderr","time":"2017-08-29T17:16:59.46005997Z"}
{"log":" File \"/usr/local/lib/python3.6/site-packages/gunicorn/workers/base.py\", line 135, in load_wsgi\n","stream":"stderr","time":"2017-08-29T17:16:59.46006246Z"}
{"log":" self.wsgi = self.app.wsgi()\n","stream":"stderr","time":"2017-08-29T17:16:59.46006513Z"}
{"log":" File \"/usr/local/lib/python3.6/site-packages/gunicorn/app/base.py\", line 67, in wsgi\n","stream":"stderr","time":"2017-08-29T17:16:59.460067413Z"}
{"log":" self.callable = self.load()\n","stream":"stderr","time":"2017-08-29T17:16:59.460069991Z"}
{"log":" File \"/usr/local/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py\", line 65, in load\n","stream":"stderr","time":"2017-08-29T17:16:59.460072224Z"}
{"log":" return self.load_wsgiapp()\n","stream":"stderr","time":"2017-08-29T17:16:59.46007479Z"}
{"log":" File \"/usr/local/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py\", line 52, in load_wsgiapp\n","stream":"stderr","time":"2017-08-29T17:16:59.460077063Z"}
{"log":" return util.import_app(self.app_uri)\n","stream":"stderr","time":"2017-08-29T17:16:59.460079605Z"}
{"log":" File \"/usr/local/lib/python3.6/site-packages/gunicorn/util.py\", line 352, in import_app\n","stream":"stderr","time":"2017-08-29T17:16:59.460081902Z"}
{"log":" __import__(module)\n","stream":"stderr","time":"2017-08-29T17:16:59.460084489Z"}
{"log":"ModuleNotFoundError: No module named 'turtle.wsgi'; 'turtle' is not a package\n","stream":"stderr","time":"2017-08-29T17:16:59.460086702Z"}
{"log":"[2017-08-29 17:16:59 +0000] [7] [INFO] Worker exiting (pid: 7)\n","stream":"stderr","time":"2017-08-29T17:16:59.460089174Z"}
Project Structure
web
- app
- static
- staticfiles
- turtle
- __init__.py
- settings.py
- urls.py
- wsgi.py
- Dockerfile
- manage.py