上一章咱們成功搭建了容器化的 Django 項目,用到的數據庫爲默認的 Sqlite。Sqlite 雖然簡單易用,可是線上部署時一般會選擇更高效、更可靠的數據庫,好比 MySQL。python
本章將在上一章的基礎上,修改並構建 Docker + Django + MySQL 的容器項目。mysql
咱們在學習面向對象的編程語言時,會千方百計把功能獨立的模塊給獨立出來,方便複用和維護。git
容器也是同樣的。雖然理論上能夠把全部組件塞到同一個容器中去,但更好的作法是各模塊在單獨容器中,只要保持必要的通訊就能夠了。github
也就是說,本教程中如今須要兩個容器了:sql
因此如何構建 MySQL 鏡像?別擔憂,這麼經常使用的鏡像官方已經幫你構建好了,只須要把它從倉庫拉取到本地就能夠了。docker
修改上一章寫的 docker-compose.yml
,增長 MySQL 容器:shell
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
容器:django
image
:從倉庫拉取 MySQL 5.7 。最新版本爲 MySQL 8,不過很坑的是新版本修改了用戶登陸的驗證方法,致使很容易出現沒法經過身份驗證的問題。教程爲了簡單起見選用 5.7 版本。後期會在教程示例代碼中添加mysql-8分支並給出操做方法,有興趣的讀者能夠查看。volumes
:定義卷(這裏實際是掛載),上一章已經講過了,它實現了宿主機和容器目錄的映射。功能是將容器中的 MySQL 數據映射到宿主機。ports
:MySQL 默認通訊端口爲 3306 。environment
:定義容器的環境變量,設置了 MySQL 的 root 用戶的密碼、數據庫的名稱。這裏爲何要用卷?就讓數據在容器中、保持隔離很差嗎?把數據保存在容器中,理論上確實是能夠的,但有一個致命的問題,即數據和容器的生命週期掛鉤了:萬一哪天手賤把容器給刪了,連同裏面的數據隨風而逝,你就是全公司那個刪庫跑路的傳奇人物了。要知道容器的生命週期可能會很是短暫,刪除指令也至關順滑(docker-compose down
)。將數據映射到宿主機,容器即便被刪除掉,但數據仍是安全的躺在你的服務器中的。換句話說,容器內部很是適合運行無狀態的應用;涉及到如數據之類有狀態的東西,必定要謹慎思考。編程
接下來修改 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 項目。