├── .gitignore ├── Dockerfile ├── _starter.zip ├── app ├── app.py └── tests.py ├── circle.yml ├── config ├── app.ini ├── nginx.conf └── supervisor.conf └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.DS_Store 3 | env -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # start with a base image 2 | FROM ubuntu:14.10 3 | MAINTAINER Real Python 4 | 5 | # install dependencies 6 | RUN apt-get update 7 | RUN apt-get install -y nginx 8 | RUN apt-get install -y supervisor 9 | RUN apt-get install -y python3-pip 10 | RUN pip3 install uwsgi flask 11 | 12 | # update working directories 13 | ADD ./app /app 14 | ADD ./config /config 15 | 16 | # setup config 17 | RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf 18 | RUN rm /etc/nginx/sites-enabled/default 19 | 20 | RUN ln -s /config/nginx.conf /etc/nginx/sites-enabled/ 21 | RUN ln -s /config/supervisor.conf /etc/supervisor/conf.d/ 22 | 23 | EXPOSE 80 24 | CMD ["supervisord", "-n"] -------------------------------------------------------------------------------- /_starter.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/realpython/flask-docker-workflow/49ed3ad3af9b5e564ccd7576ac5dad433640bdf7/_starter.zip -------------------------------------------------------------------------------- /app/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Flask, jsonify 3 | 4 | app = Flask(__name__) 5 | 6 | 7 | @app.route('/') 8 | def index(): 9 | return 'Flask is running on Docker!' 10 | 11 | 12 | @app.route('/data') 13 | def cities(): 14 | data = { 15 | "cities": ["Seattle", "San Francisco", "Chicago", 16 | "New York", "Denver", "San Diego", "Tokyo", "Warsaw"] 17 | } 18 | return jsonify(data) 19 | 20 | 21 | if __name__ == '__main__': 22 | port = int(os.environ.get('PORT', 5000)) 23 | app.run(host='0.0.0.0', port=port) 24 | -------------------------------------------------------------------------------- /app/tests.py: -------------------------------------------------------------------------------- 1 | from app import app 2 | import unittest 3 | 4 | 5 | class MainTestCase(unittest.TestCase): 6 | 7 | def test_data(self): 8 | tester = app.test_client(self) 9 | response = tester.get('/data') 10 | self.assertEqual(response.status_code, 200) 11 | self.assertEqual(response.content_type, 'application/json') 12 | self.assertIn('Seattle', response.data) 13 | 14 | def test_index(self): 15 | tester = app.test_client(self) 16 | response = tester.get('/') 17 | self.assertEqual(response.status_code, 200) 18 | self.assertEqual(response.data, 'Flask is running on Docker!') 19 | 20 | 21 | if __name__ == '__main__': 22 | unittest.main() 23 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | services: 3 | - docker 4 | 5 | dependencies: 6 | override: 7 | - docker info 8 | - docker build -t mjhea0/flask-docker-workflow . 9 | 10 | test: 11 | override: 12 | - docker run -d -p 80:80 mjhea0/flask-docker-workflow; sleep 10 13 | - curl --retry 10 --retry-delay 5 -v http://localhost:80 14 | - pip install -r requirements.txt 15 | - python app/tests.py 16 | 17 | deployment: 18 | hub: 19 | branch: master 20 | commands: 21 | - $DEPLOY -------------------------------------------------------------------------------- /config/app.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | chdir = /app/ 3 | chmod-socket = 666 4 | master = true 5 | module = app:app 6 | processes = 4 7 | socket = /config/app.sock 8 | -------------------------------------------------------------------------------- /config/nginx.conf: -------------------------------------------------------------------------------- 1 | upstream app { 2 | server unix:/config/app.sock; 3 | } 4 | 5 | server { 6 | listen 80 default_server; 7 | charset utf-8; 8 | 9 | location / { 10 | uwsgi_pass app; 11 | uwsgi_param CONTENT_LENGTH $content_length; 12 | uwsgi_param CONTENT_TYPE $content_type; 13 | uwsgi_param DOCUMENT_ROOT $document_root; 14 | uwsgi_param HTTPS $https if_not_empty; 15 | uwsgi_param PATH_INFO $document_uri; 16 | uwsgi_param QUERY_STRING $query_string; 17 | uwsgi_param REMOTE_ADDR $remote_addr; 18 | uwsgi_param REMOTE_PORT $remote_port; 19 | uwsgi_param REQUEST_METHOD $request_method; 20 | uwsgi_param REQUEST_URI $request_uri; 21 | uwsgi_param SERVER_PORT $server_port; 22 | uwsgi_param SERVER_NAME $server_name; 23 | uwsgi_param SERVER_PROTOCOL $server_protocol; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /config/supervisor.conf: -------------------------------------------------------------------------------- 1 | [program:app] 2 | command = uwsgi --ini /config/app.ini 3 | 4 | [program:nginx] 5 | command = service nginx restart 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==0.10.1 --------------------------------------------------------------------------------