1. 程式人生 > 程式設計 >Django-Docker容器化部署:Django-Docker-MySQL部署

Django-Docker容器化部署:Django-Docker-MySQL部署

上一章我們成功搭建了容器化的 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 專案。