许多Python库,都需要Linux环境,比如uvloop、gunicorn、Tensorflow、Postgres、eventlet等等。
有时不得不在Windows下开发Flask app时,借助Cygwin也只能完成一小部分任务(Windows环境(Cygwin)下,使用PostgreSQL, Redis)
所以,还是拥抱Docker吧!
repo: https://github.com/kevinqqnj/flask-template-postgres-redis-in-docker
目标:
无论什么环境,只要有Docker,执行一行docker-compose命令,就能建立起一模一样的开发环境,省却了各种繁琐配置。
当然,数据库要能执久化,同一台电脑上不需要重复建数据
前提:
- 电脑安装好Docker环境
- 我是用的Win7 + VirtualBox
- 安装Docker-Toolbox
- psql (Postgresql命令行工具) - 可选
-
VirtualBox设置 -> 网络 -> 端口转发(有时网页调试打不开,试试这个)
步骤:
1. git clone 模板,到你的本地目录
注:VirtualBox默认设置的共享文件夹是 C:\User\
,如果想让Docker挂载你本地目录的话,本地目录必须要在C:\User\
文件夹内。不然你就要设置其它的共享文件夹。
git clone https://github.com/kevinqqnj/flask-template-postgres-redis-in-docker.git
cd flask-template-postgres-redis-in-docker
2. 运行Docker Quickstart Terminal
先用国内速度快的镜像,预先下载好images:
docker pull registry.docker-cn.com/library/python:3
docker pull registry.docker-cn.com/library/postgres:9
docker pull registry.docker-cn.com/library/redis
3. 创建本地Volume,postgres数据库内容存放在此,可以执久化保存,就算电脑重启,数据库也不会丢
docker volume create pgdata
4. 开始 docker-compose,创建本地开发环境:
$ docker-compose up --build
Building web
Step 1/7 : FROM python:3
---> 500d0dca385d
Step 2/7 : ENV PYTHONUNBUFFERED 1
---> Using cache
---> 4f24d910ee44
Step 3/7 : ENV LANG C.UTF-8
---> Using cache
---> 9439fe70bc16
Step 4/7 : RUN mkdir /code
---> Using cache
---> fc838cf209fb
Step 5/7 : WORKDIR /code
---> Using cache
---> e3817459d383
Step 6/7 : ADD requirements.txt /code/
---> 7889368fb93a
Step 7/7 : RUN pip install -r requirements.txt
。。。
Successfully built 41ea5f76c4ec
Successfully tagged flasktemplateadvanced_web:latest
Recreating flasktemplateadvanced_db_1 ...
Recreating flasktemplateadvanced_db_1 ... done
Recreating flasktemplateadvanced_web_1 ... done
Attaching to flasktemplateadvanced_redis_1, flasktemplateadvanced_db_1, flasktemplateadvanced_web_1
redis_1 | 1:C 21 Mar 13:35:05.952 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 21 Mar 13:35:05.955 # Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=1, just started
db_1 | LOG: database system was shut down at 2018-03-21 13:33:09 UTC
db_1 | LOG: MultiXact member wraparound protections are now enabled
redis_1 | 1:C 21 Mar 13:35:05.958 # Warning: no config file specified, using the default config. In order to specify a
config file use redis-server /path/to/redis.conf
db_1 | LOG: database system is ready to accept connections
redis_1 | 1:M 21 Mar 13:35:05.967 * Running mode=standalone, port=6379.
redis_1 | 1:M 21 Mar 13:35:05.971 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/co
re/somaxconn is set to the lower value of 128.
redis_1 | 1:M 21 Mar 13:35:05.971 # Server initialized
redis_1 | 1:M 21 Mar 13:35:05.972 # WARNING overcommit_memory is set to 0! Background save may fail under low memory co
ndition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl
vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 21 Mar 13:35:05.972 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This
will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/t
ransparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Re
dis must be restarted after THP is disabled.
redis_1 | 1:M 21 Mar 13:35:05.978 * DB loaded from disk: 0.006 seconds
这时,Redis服务已经正常工作了。打开浏览器:http://localhost:5000
5. Postgres服务:
环境变量文件在 .env
里,
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_DB=myapp_db
DB_SERVICE=db
REDIS_SERVICE=redis
推荐不同的项目使用不同的database,比如这里用了:myapp_db
需要使用psql
工具创建database:
$ psql -h localhost -p 5432 -U postgres
psql (9.6.6, 服务器 9.6.8)
输入 "help" 来获取帮助信息.
postgres=# \l
数据库列表
名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限
-----------+----------+----------+------------+------------+-----------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(3 行记录)
postgres=# create database myapp_db;
CREATE DATABASE
6. 初始化数据库表格
当前Docker里,已经有名字是"web"的container了。另外打开一个“Docker Quickstart Terminal”窗口,执行命令行:
$ docker-compose run web bash
Starting flasktemplateadvanced_db_1 ... done
Starting flasktemplateadvanced_redis_1 ... done
root@7bc24648a3fc:/code# ls
Dockerfile Procfile __pycache docker-compose.yml manage.pyadmin.p runtime.txts.txt
root@7bc24648a3fc:/code# python manage.py deploy
Importing environment from .env...
Creating directory /code/migrations ... done
Creating directory /code/migrations/versions ... done
Generating /code/migrations/alembic.ini ... done
Generating /code/migrations/env.py ... done
Generating /code/migrations/script.py.mako ... done
Generating /code/migrations/README ... done
Please edit configuration/connection/logging settings in '/code/migrations/alembic.ini' before proceeding.
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'roles'
INFO [alembic.autogenerate.compare] Detected added table 'users'
INFO [alembic.autogenerate.compare] Detected added index 'ix_users_username' on '['username']'
INFO [alembic.autogenerate.compare] Detected added table 'roles_users'
Generating /code/migrations/versions/a300240f4694_.py ... done
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> a300240f4694, empty message
root@7bc24648a3fc:/code#
root@7bc24648a3fc:/code# python manage.py initrole
Importing environment from .env...
Pls input Flask admin pwd:XXXXXXX
Roles added!
root@7bc24648a3fc:/code#
7. 非首次运行docker-compose
非首次运行docker-compose,只要运行docker-compose up
就够了。
除非image内容修改,才需要重新docker-compose up --build
注意看gunicorn,配置过后,发现文件改动,能热重启,logging模式也可以在docker-compose.yml里设置。
这时,打开http://localhost:5000/admin,就能登录Flask后台,说明postgres服务正常连接了。
$ docker-compose up
Starting flasktemplateadvanced_db_1 ...
Starting flasktemplateadvanced_redis_1 ... done
Starting flasktemplateadvanced_web_1 ... done
Attaching to flasktemplateadvanced_db_1, flasktemplateadvanced_redis_1, flasktemplateadvanced_web_1
db_1 | LOG: database system was interrupted; last known up at 2018-03-21 13:37:59 UTC
db_1 | LOG: database system was not properly shut down; automatic recovery in progress
db_1 | LOG: invalid record length at 0/14EEE38: wanted 24, got 0
db_1 | LOG: redo is not required
db_1 | LOG: MultiXact member wraparound protections are now enabled
db_1 | LOG: database system is ready to accept connections
redis_1 | 1:C 21 Mar 13:40:41.171 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 21 Mar 13:40:41.179 # Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 21 Mar 13:40:41.180 # Warning: no config file specified, using the default config. In order to specify a
config file use redis-server /path/to/redis.conf
redis_1 | 1:M 21 Mar 13:40:41.200 * Running mode=standalone, port=6379.
redis_1 | 1:M 21 Mar 13:40:41.202 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/co
re/somaxconn is set to the lower value of 128.
redis_1 | 1:M 21 Mar 13:40:41.203 # Server initialized
redis_1 | 1:M 21 Mar 13:40:41.203 # WARNING overcommit_memory is set to 0! Background save may fail under low memory co
ndition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl
vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 21 Mar 13:40:41.204 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This
will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/t
ransparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Re
dis must be restarted after THP is disabled.
web_1 | [2018-03-21 13:40:43 +0000] [1] [INFO] Starting gunicorn 19.7.1
web_1 | [2018-03-21 13:40:43 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
web_1 | [2018-03-21 13:40:43 +0000] [1] [INFO] Using worker: sync
web_1 | [2018-03-21 13:40:43 +0000] [7] [INFO] Booting worker with pid: 7
web_1 | Importing environment from .env...
web_1 | [2018-03-21 13:45:31 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:16)
web_1 | [2018-03-21 13:45:31 +0000] [16] [INFO] Worker exiting (pid: 16)
web_1 | [2018-03-21 13:45:31 +0000] [19] [INFO] Booting worker with pid: 19
web_1 | Importing environment from .env...
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:15 +0000] "POST /login HTTP/1.1" 302 209 "http://localhost:5000/login" "Mozil
la/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:15 +0000] "GET / HTTP/1.1" 200 859 "http://localhost:5000/login" "Mozilla/5.0
(Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:18 +0000] "GET /admin/ HTTP/1.1" 200 2181 "http://localhost:5000/" "Mozilla/5
.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:21 +0000] "GET /admin/user/ HTTP/1.1" 200 13160 "http://localhost:5000/admin/
" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:24 +0000] "GET /admin/role/ HTTP/1.1" 200 14853 "http://localhost:5000/admin/
user/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.
36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:25 +0000] "GET /admin/user/ HTTP/1.1" 200 13160 "http://localhost:5000/admin/
role/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.
36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:49 +0000] "GET /admin/ HTTP/1.1" 200 2181 "http://localhost:5000/admin/user/"
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:52 +0000] "GET / HTTP/1.1" 200 859 "http://localhost:5000/admin/" "Mozilla/5.
0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:55 +0000] "GET / HTTP/1.1" 200 859 "http://localhost:5000/admin/" "Mozilla/5.
0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | 10.0.2.2 - - [21/Mar/2018:13:46:57 +0000] "GET / HTTP/1.1" 200 860 "http://localhost:5000/admin/" "Mozilla/5.
0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
web_1 | [2018-03-21 14:03:12 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:19)
web_1 | [2018-03-21 14:03:12 +0000] [19] [INFO] Worker exiting (pid: 19)
web_1 | [2018-03-21 14:03:12 +0000] [22] [INFO] Booting worker with pid: 22
docker-compose.yml文件解析:
volumes:
:映射了源代码目录到Docker里。你在本地修改了任何源代码,立马能看到新的运行结果,无需重启build
command:
:gunicorn会热重启、logging level可设置
depends_on
:依赖于db, redis两个服务,Docker会内部自动关联连接
services:
web:
build: .
command: gunicorn -b 0.0.0.0:5000 --reload --access-logfile '-' --log-level info manage:app
env_file: .env
volumes:
- ./:/code
ports:
- "5000:5000"
depends_on:
- db
- redis
db
, redis
是服务名字,在Flask config.py文件里,也会使用这名字,来连接postgres/redis
redis:
image: redis
volumes:
- redis_data:/data
ports:
- "6379:6379"
db:
restart: always
image: postgres:9
env_file: .env
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
必须要有独立的volumes
字段,这样才能数据执久化。
volumes:
redis_data:
pgdata:
注:docker python:3 是用的Debian系统
好了,小伙伴们,只需愉快地关注开发,不用操心环境的事了!
计划:deployment, 关注下k8s - kubernetes
觉得好用,github点个赞哦~~