上一章咱們成功搭建了容器化的 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 項目。