随着Docker的普及成熟,已经逐渐成为部署项目的首选,今天来和大家分享下如何使用docker部署django技术栈项目。
我们这里说的Django技术栈为:python3.6、Django2.2、redis、mysql、celery、gunicorn和nginx。在实际的生产项目中,这些组件分布在集群的不同机器,如Nginx、redis和Mysql可能会有单独的团队或部门负责。涉及的部署架构和容器的编排会更为复杂,本文暂不去深究。本文主要介绍,如何使用 docker-compose 来编排这些组件,这种方式适用于测试环境的部署或者你的个人 sideproject 的部署。
本文默认你已经了解 docker 和 docker-compose 的一些基本知识,若你不了解,可阅读下面这些资料:
- Docker知识大全
- Docker官方文档
- Docker Compose文档
下面我们来说下如何部署。
项目组织结构
首先,看下我们的项目组织结构,结构如下:
├── LICENSE ├── README.md ├── compose │ ├── celery │ │ ├── Dockerfile │ │ ├── celery-beat.sh │ │ └── celery.sh │ ├── mysql │ │ └── my.cnf │ ├── nginx │ │ └── nginx.conf │ └── web │ ├── Dockerfile │ ├── entrypoint.sh │ ├── gunicorn.conf │ └── gunicorn.sh ├── docker-compose.yml ├── docker_django_demo │ ├── __init__.py │ ├── celery.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── env.tpl ├── manage.py ├── requirements.txt
除了Django的项目文件外,主要增加了 compose 配置文件目录和 docker-compose.yml 配置文件。
- compose目录主要存放各组件的dockerfile文件和启动脚本。
- docker-compose.yml 是docker-compose的编排配置文件。
编写Dockerfile 及启动初始化脚本
在docker-compose中,容器的启动有两种方法,一种是直接使用公共的镜像来启动容器,另一种是通过我们自己编写的Dockerfile。因为我们要安装额外的工具包和初始化相关配置,web和celery组件我们使用自定义的Dockerfile方式。
web容器的 compose/web/Dockerfile :
FROM python:3.6 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY ./requirements.txt /code/ RUN pip install --no-cache-dir -r requirements.txt && rm -rf requirements.txt COPY . /code/ COPY ./compose/web/*.sh /code/ RUN sed -i 's/\r//' gunicorn.sh && chmod +x gunicorn.sh && sed -i 's/\r//' entrypoint.sh && chmod +x entrypoint.sh ENTRYPOINT ["/bin/bash", "entrypoint.sh"]
web容器的其他文件:
- compose/web/entrypoint.sh web容器的启动脚本,执行一些初始化或检测逻辑。
- compose/web/gunicorn.conf gunicorn配置文件。
- compose/web/gunicorn.sh gunicorn的启动脚本。
celery的Dockerfile:
FROM python:3.6 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY ./requirements.txt /code/ COPY ./compose/celery/*.sh /code/ RUN pip install --no-cache-dir -r requirements.txt && rm -rf requirements.txt && sh init_env.sh COPY . /code/ COPY ./compose/celery/*.sh /code/ RUN sed -i 's/\r//' celery.sh && chmod +x celery.sh && sed -i 's/\r//' celery-beat.sh && chmod +x celery-beat.sh
celery的其他文件:
- compose/celery/celery.sh celery的启动脚本。
- compose/celery/celery-beat.sh celery-beat的启动脚本。
编写Compose启动配置文件
docker-compose 配置如下:
version: '2' services: redis: image: redis ports: - "6379:6379" db: restart: always image: mysql:5.7.19 # command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ./compose/mysql/:/etc/mysql/conf.d - ./db:/var/lib/mysql # for test ports: - "127.0.0.1:3307:3306" # (HOST:CONTAINER) env_file: - .env web: # restart: always build: context: . dockerfile: ./compose/web/Dockerfile command: sh gunicorn.sh # ["/bin/bash", "gunicorn.sh"] ports: - "8080:8002" # (HOST:CONTAINER) volumes: - ./logs:/var/logs/ - ./collect_static:/code/collect_static - ./static:/code/static - ./templates:/code/templates - ./uploads:/code/uploads env_file: .env depends_on: - redis - db nginx: restart: always image: nginx:1.13.0 volumes: - ./compose/nginx:/etc/nginx/conf.d/ - ./staticfiles:/code/staticfiles - ./logs:/var/log/nginx ports: - "80:80" # (HOST:CONTAINER) depends_on: - web celery: build: context: . dockerfile: ./compose/celery/Dockerfile command: sh celery.sh volumes: - ./logs:/var/logs/ - ./uploads:/code/uploads depends_on: - redis - db env_file: .env celery-beat: build: context: . dockerfile: ./compose/celery/Dockerfile command: sh celery-beat.sh volumes: - ./logs:/var/logs/ depends_on: - redis - db env_file: .env
celery 的worker 和beat这里我们使用同一个镜像Dockerfile, 按照一个镜像一个进程的原则,启动两个容器来分别跑worker和beat进程。
编译测试
编写好配置文件之后,编译镜像测试运行:
docker-compose build docker-compose up # 前台运行 docker-compose up -d # 无误后可后台运行
docker-compose ps 可以看到启动好的容器:
$ docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------------- dockerdjangodemo_celery-beat_1 sh celery-beat.sh Up dockerdjangodemo_celery_1 sh celery.sh Up dockerdjangodemo_db_1 docker-entrypoint.sh mysqld Up 127.0.0.1:3307->3306/tcp dockerdjangodemo_nginx_1 nginx -g daemon off; Up 0.0.0.0:80->80/tcp dockerdjangodemo_redis_1 docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp dockerdjangodemo_web_1 /bin/bash entrypoint.sh sh ... Up 0.0.0.0:8080->8002/tcp
映射端口可根据自己的实际情况调整。
问题
下面说下在构建过程中的几个需要注意的问题。
mysql 编码问题
docker 提供的mysql镜像,默认编码为 latin1 , 在保存中文时会显示乱码。官方提供了一种修改编码方式的方法,在启动脚本后指定编码格式,文档可见这里。mysql容器5.7.19版本可直接在docker-compose.yml 中的command后跟上参数 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci 。这种方式,只是修改server端的编码。可直接使用配置文件覆盖的方式,指定所有的编码格式。
配置如下:
[mysqld] default-storage-engine=INNODB character-set-server=utf8mb4 collation-server=utf8mb4_general_ci init-connect='SET NAMES utf8mb4' init_connect='SET collation_connection = utf8mb4_general_ci' skip-character-set-client-handshake # 跳过客户端的编码配置,客户端直接使用服务端的编码配置 bind-address = 0.0.0.0
注:mysql 5.7.19 配置文件方式成功,5.7.4、5.7.17 均失败,可做参考。
web等mysql启动完成后再继续
mysql 容器在启动起来之前是无法接受数据库链接的,在web启动初始化时,若数据库还没有启动好会导致web容器启动失败直接退出。我们可以增加在web容器启动时增加检测脚本,数据库连通之后,再继续。
脚本如下:
#!/usr/bin/env bash set -o errexit set -o pipefail echo $MYSQL_PASSWORD echo $MYSQL_DATABASE echo $MYSQL_HOST echo $MYSQL_USER echo $MYSQL_PORT function mysql_ready(){ python << END import sys import pymysql try: conn = pymysql.connect(host="db", port=3306, user="root", passwd="$MYSQL_ROOT_PASSWORD", db='$MYSQL_DATABASE', charset='utf8') except pymysql.err.OperationalError: sys.exit(-1) sys.exit(0) END } until mysql_ready; do >&2 echo "MySQL is unavailable - sleeping" sleep 1 done >&2 echo "MySQL is up - continuing..."
总结
到此,使用docker来部署django技术栈服务就完成了,完整的项目代码,大家可参阅 docker-django-demo 。
文章开始说了,该部署方式不适合大型网站的线上生产服务,耦合度太高,不好维护等存在着许多问题。但是,部署自己的sideproject或者测试环境,在硬件资源有限的情况的下还是非常不错的。除了减少环境部署搭建的麻烦外,迁移起来也是很方便的。
demo 项目中也有些开发环境下如何使用docker的案例,但是个人一直认为docker更适合部署,在开发环境方便不如直接搭建来的灵活方便。欢迎大家留言,共同讨论docker在开发和部署上的使用心得。
参考
cookiecutter-django
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
docker部署django
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。