Django-Docker容器化部署:

发布时间:2019-10-11 09:02:34编辑:auto阅读(2097)

    上一章我们成功搭建了容器化的 Django 项目,用到的数据库为默认的 Sqlite。Sqlite 虽然简单易用,但是线上部署时通常会选择更高效、更可靠的数据库,比如 MySQL。

    本章将在上一章的基础上,修改并构建 Docker + Django + MySQL 的容器项目。

    Docker-compose

    我们在学习面向对象的编程语言时,会想方设法把功能独立的模块给独立出来,方便复用和维护。

    容器也是一样的。虽然理论上可以把所有组件塞到同一个容器中去,但更好的做法是各模块在单独容器中,只要保持必要的通信就可以了。

    也就是说,本教程中现在需要两个容器了:

    • 名称叫 app 的 Django 容器
    • 名称叫 db 的 MySQL 容器

    所以如何构建 MySQL 镜像?别担心,这么常用的镜像官方已经帮你构建好了,只需要把它从仓库拉取到本地就可以了。

    修改上一章写的 docker-compose.yml ,增加 MySQL 容器:

    version: "3"
    services:
      app:
        restart: always
        build: .
        command: bash -c "python3 manage.py migrate && python3 manage.py runserver 0.0.0.0:8000"
        volumes:
          - .:/code
        ports:
          - "8000:8000"
        depends_on:
          - db
      db:
        image: mysql:5.7
        volumes:
          - "./mysql:/var/lib/mysql"
        ports:
          - "3306:3306"
        restart: always
        environment:
          - MYSQL_ROOT_PASSWORD=mypassword
          - MYSQL_DATABASE=django_app

    app 容器的 command 指令做了修改,让其在运行前先执行数据迁移;新增了配置 depends_on ,意思是此容器需要等待 db 容器启动完毕才能够启动。

    分析一下新添加的 db 容器:

    • image :从仓库拉取 MySQL 5.7 。最新版本为 MySQL 8,不过很坑的是新版本修改了用户登录的验证方法,导致很容易出现无法通过身份验证的问题。教程为了简单起见选用 5.7 版本。后期会在教程示例代码中添加[mysql-8]()分支并给出操作方法,有兴趣的读者可以查看。
    • volumes :定义卷(这里实际是挂载),上一章已经讲过了,它实现了宿主机和容器目录的映射。功能是将容器中的 MySQL 数据映射到宿主机。
    • ports :MySQL 默认通信端口为 3306 。
    • environment :定义容器的环境变量,设置了 MySQL 的 root 用户的密码、数据库的名称。

    这里为什么要用?就让数据在容器中、保持隔离不好吗?把数据保存在容器中,理论上确实是可以的,但有一个致命的问题,即数据和容器的生命周期挂钩了:万一哪天手贱把容器给删了,连同里面的数据随风而逝,你就是全公司那个删库跑路的传奇人物了。要知道容器的生命周期可能会非常短暂,删除指令也相当顺滑(docker-compose down)。将数据映射到宿主机,容器即使被删除掉,但数据还是安全的躺在你的服务器中的。换句话说,容器内部非常适合运行无状态的应用;涉及到如数据之类有状态的东西,一定要谨慎思考。

    Dockerfile

    接下来修改 Dockerfile

    FROM python:3.7
    ENV PYTHONUNBUFFERED 1
    
    # 添加这两行
    RUN apt-get update
    RUN apt-get install python3-dev default-libmysqlclient-dev -y
    
    RUN mkdir /code
    WORKDIR /code
    RUN pip install pip -U
    ADD requirements.txt /code/
    RUN pip install -r requirements.txt
    ADD . /code/

    增加的两行代码在系统中安装了 MySQL 的连接器,具体解释见官方文档

    其他配置

    修改 requirements.txt ,增加 MySQL 驱动:

    django==2.2
    mysqlclient==1.3.14

    然后还需要修改 django_app/settings.py ,将数据库设置为 MySQL:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'django_app',
            'USER': 'root',
            'PASSWORD': 'mypassword',
            'HOST': 'db',
            'PORT': '3306',
            'OPTIONS': {'charset': 'utf8mb4'},
        }
    }

    注意 HOST 填写的是容器的名称,即 db 。

    这就可以啦。接下来测试。

    测试

    测试之前,请先确认没有其他程序占用了 3306 端口,比如宿主机安装的 MySQL。

    重新生成镜像:

    $ docker-compose build

    生成并启动容器:

    $ docker-compose up
    
    Creating network "django_app_default" with the default driver
    Creating django_app_db_1 ... done
    Creating django_app_app_1 ... done
    Attaching to django_app_db_1, django_app_app_1
    db_1   | 2019-10-06T12:24:57.183860Z 0 [Note] mysqld (mysqld 5.7.27) starting as process 1 ...
    
    ...
    
    db_1   | 2019-10-06T12:24:58.120480Z 0 [Note] mysqld: ready for connections.
    db_1   | Version: '5.7.27'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    
    app_1  | Operations to perform:
    app_1  |   Apply all migrations: admin, auth, contenttypes, sessions
    app_1  | Running migrations:
    app_1  |   Applying contenttypes.0001_initial... OK
    ...
    app_1  |   Applying sessions.0001_initial... OK
    
    app_1  | Watching for file changes with StatReloader
    app_1  | Performing system checks...
    app_1  | 
    app_1  | System check identified no issues (0 silenced).
    app_1  | October 06, 2019 - 12:24:58
    app_1  | Django version 2.2, using settings 'django_app.settings'
    app_1  | Starting development server at http://0.0.0.0:8000/
    app_1  | Quit the server with CONTROL-C.

    打开浏览器访问 127.0.0.1:8000 ,又能看到 Django 小火箭啦。

    注意:第一次启动容器时可能会出现无法连接 MySQL 的错误,这是由于虽然 db 容器已经启动,但初始化并未完成;重新启动容器之后就可以正常工作了。若多次启动都无法正常工作,那就是别的原因了,好好检查吧。

    总结

    本章加入了 MySQL 容器,并实现了多容器协同工作。

    下一章将实现正式部署的 Docker + Django + MySQL + Nginx + Gunicorn 项目。


关键字