docker-compose:使用docker-compose部署nginx+supervisor+uwsgi+flask程序(mongodb)
0 写在前面
百度搜索的文档渣的要命,一定要Google,一定要GitHub。
1 目录层次
我们必须清楚我们docker-compose.yaml文件和Dockerfile的位置以及其他配置脚本的位置
假设我们有一个路径:/data/www/backend
那么该目录下应该是:
web/
docker-compose.yaml
而配置文件的docker-compose.yaml如下:
version: '2' services: web: build: ./web container_name: "web" volumes: - /data/www:/data/www ports: - 80:80 depends_on: - mongodb mongodb: image: mongo:latest container_name: "mongodb" environment: - MONGO_DATA_DIR=/data/db - MONGO_LOG_DIR=/dev/null volumes: - ./data/db:/data/db
加入了kong API getway 网关的docker-compose.yaml
version: '2' services: web: build: ./web container_name: "web" volumes: - /data/www:/data/www ports: - 80:80 depends_on: - mongodb mongodb: image: mongo:latest container_name: "mongodb" environment: - MONGO_DATA_DIR=/data/db - MONGO_LOG_DIR=/dev/null volumes: - ./data/db:/data/db - ./data/www:/data/www kong-database: image: postgres:9.4 container_name: "kong-database" ports: - 5432:5432 environment: - POSTGRES_USER=kong - POSTGRES_DB=kong volumes: - ./var/lib/postgresql/data:/var/lib/postgresql/data kong: image: kong:0.9.1 container_name: kong environment: - KONG_DATABASE=postgres - KONG_PG_HOST=kong-database restart: always ports: - 8000:8000 - 8443:8443 - 8001:8001 - 7946:7946 - 7946:7946/udp links: - kong-database
web 下面的目录是:
app/
Dockerfile
entrypoint.sh
start.sh
app里面的目录是,是自己的整个程序:
aliyunapi/
wechatapi/
myutils/
static/
templates/
website/
app.py
create_db.py
prestart.sh
requirements.txt
uwsgi.ini
readme.txt
但是最简单的目录是你自己开发的:
website/
app.py
create_db.py
prestart.sh
requirements.txt
uwsgi.ini
readme.txt
2 基本逻辑
基本镜像是基于tiangolo/uwsgi-nginx:python2.7,github地址
整体逻辑是:git clone 整体文件包,进入python 2.7,因为我是依赖python2.7,在你看不懂Dockerfile和docker-compose配置文件以及其他配置文件时候不要轻易修改。
所有的原来配置文件不要动,把你自己的程序根目录下的文件统一复制到app中去
命令启动的执行流程,详细看上面compose配置文件:docker-compose up
(1)根据compose配置文件,web depends_on mongodb, 因此先用mongodb的纯镜像构造容器并且暴露mongodb的端口27017,等待连接
(2)build web(build dockerfile)构造主程序镜像,其次是执行入口脚本,enterstart.sh—>start.sh—>prestart.sh(处理docker纯镜像容器数据库,建立数据库,建表,设置索引)
(3)启动主程序的命令传递:supervisor->uwsgi->flask
3 具体脚本配置
(1) Dockerfile:
FROM tiangolo/uwsgi-nginx:python2.7 RUN pip install flask RUN apt-get update && apt-get install docker # By default, allow unlimited file sizes, modify it to limit the file sizes # To have a maximum of 1 MB (Nginx's default) change the line to: # ENV NGINX_MAX_UPLOAD 1m ENV NGINX_MAX_UPLOAD 0 # By default, Nginx listens on port 80. # To modify this, change LISTEN_PORT environment variable. # (in a Dockerfile or with an option for `docker run`) ENV LISTEN_PORT 80 # Which uWSGI .ini file should be used, to make it customizable ENV UWSGI_INI /app/uwsgi.ini # URL under which static (not modified by Python) files will be requested # They will be served by Nginx directly, without being handled by uWSGI ENV STATIC_URL /static # Absolute path in where the static files wil be ENV STATIC_PATH /app/static # If STATIC_INDEX is 1, serve / with /static/index.html directly (or the static URL configured) # ENV STATIC_INDEX 1 ENV STATIC_INDEX 0 # Add demo app COPY ./app /app WORKDIR /app RUN pip install -r /app/requirements.txt RUN cd /app/aliyunapi/dysms_python && python setup.py install # Make /app/* available to be imported by Python globally to better support several use cases like Alembic migrations. ENV PYTHONPATH=/app # Copy start.sh script that will check for a /app/prestart.sh script and run it before starting the app COPY start.sh /start.sh RUN chmod +x /start.sh # Copy the entrypoint that will generate Nginx additional configs COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] # Run the start script, it will check for an /app/prestart.sh script (e.g. for migrations) # And then will start Supervisor, which in turn will start Nginx and uWSGI CMD ["/start.sh"]
(2) entrypoint.sh
#! /usr/bin/env bash set -e # Get the maximum upload file size for Nginx, default to 0: unlimited USE_NGINX_MAX_UPLOAD=${NGINX_MAX_UPLOAD:-0} # Generate Nginx config for maximum upload file size echo "client_max_body_size $USE_NGINX_MAX_UPLOAD;" > /etc/nginx/conf.d/upload.conf # Get the number of workers for Nginx, default to 1 USE_NGINX_WORKER_PROCESSES=${NGINX_WORKER_PROCESSES:-1} # Modify the number of worker processes in Nginx config sed -i "/worker_processes\s/c\worker_processes ${USE_NGINX_WORKER_PROCESSES};" /etc/nginx/nginx.conf # Get the URL for static files from the environment variable USE_STATIC_URL=${STATIC_URL:-'/static'} # Get the absolute path of the static files from the environment variable USE_STATIC_PATH=${STATIC_PATH:-'/app/static'} # Get the listen port for Nginx, default to 80 USE_LISTEN_PORT=${LISTEN_PORT:-80} # Generate Nginx config first part using the environment variables echo "server { listen ${USE_LISTEN_PORT}; location / { try_files \$uri @app; } location @app { include uwsgi_params; uwsgi_pass unix:///tmp/uwsgi.sock; } location $USE_STATIC_URL { alias $USE_STATIC_PATH; }" > /etc/nginx/conf.d/nginx.conf # If STATIC_INDEX is 1, serve / with /static/index.html directly (or the static URL configured) if [[ $STATIC_INDEX == 1 ]] ; then echo " location = / { index $USE_STATIC_URL/index.html; }" >> /etc/nginx/conf.d/nginx.conf fi # Finish the Nginx config file echo "}" >> /etc/nginx/conf.d/nginx.conf exec "$@"
(3) start.sh
#! /usr/bin/env bash set -e # If there's a prestart.sh script in the /app directory, run it before starting PRE_START_PATH=/app/prestart.sh echo "Checking for script in $PRE_START_PATH" if [ -f $PRE_START_PATH ] ; then echo "Running script $PRE_START_PATH" source $PRE_START_PATH else echo "There is no script $PRE_START_PATH" fi # Start Supervisor, with Nginx and uWSGI exec /usr/bin/supervisord
(4) uwsgi.ini
[uwsgi] module = app callable = application
(5) prestart.sh
#!/bin/bash python create_db.py
(6) create_db.py
from pymongo import MongoClient import datetime client = MongoClient('mongodb://mongodb:27017') try: client except Exception as e: raise e if client: db_test = client.get_database('test') users = db_test.get_collection('users') users.insert_one({'title': 't1'}) print(users) #我简单写的,自己要改
(7) app.py
import os import sys from flask import Flask from website.app import create_app base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, base_dir) print(sys.path) application = create_app({ 'SECRET_KEY': '123456', 'UPLOAD_FOLDER': '/static/tmp/uploads', 'ALLOWED_EXTENSIONS': set(['bmp', 'png', 'jpg', 'jpeg', 'gif']), 'MONGO_URI': 'mongodb://mongodb:27017/test', 'MONGO_USERNAME': 'root', 'MONGO_PASSWORD': 'root', 'MONGO_CONNECT': False, }) if __name__ == '__main__': application.run(host='0.0.0.0', port=6000,debug=True)
(8) requirements.txt
flask>=1.0.2 flask-pymongo>=0.5.2 pymysql>=0.8.1 flask_cors pymongo PyMySQL>=0.8.1 authlib
4 运行指令
docker-compose up -d 启动
docker-compose down 终止
docker-compose stop web
docker-compose start web