Django-Docker容器化部署:Django-Docker本地部署

本章將在本地搭建一個容器化的 Django 項目,感覺 Docker 的運做方式。python

前期準備

開發環境

雖然有基於 Windows 的 Docker 版本,但各方面兼容作得都不太好(安裝也麻煩些),所以建議讀者在學習前,自行安裝好 Linux 或 Mac 系統。固然你願意折騰的話,在 Windows 上搞也行。mysql

別擔憂,之後開發 Django 項目仍然能夠在 Windows 下進行,僅僅是開發時不使用 Docker 而已。linux

軟件安裝

  • Docker:學習 Docker 固然要安裝 Docker 軟件了(免費的社區版),安裝方法見官方文檔
  • Docker-compose:這是 Docker 官方推出的用於編排、運行多個容器的工具,安裝方法見官方文檔。本教程大部份內容都與它有關。
  • Python3:教程部署的是 Django 項目,那 Python3 是固然要有的了(包括 python 的包管理工具 pip)。

準備就緒後就繼續下一步吧。git

建立 Django 項目

打開 Linux/Mac 的終端,安裝 Django 庫:github

$ pip install django==2.2
複製代碼

在一個你喜歡得位置(好比/home/)建立新的 Django 項目:web

$ django-admin startproject django_app
複製代碼

進入項目根目錄:sql

$ cd django_app
複製代碼

教程後面的內容所有都在此目錄中操做了。爲方便閱讀,命令提示符 $ 表明目前在項目根目錄 django_app/mysql $ 則表明目前在目錄 django_app/mysql/ 中,請讀者操做時稍加留意當前的工做目錄。docker

而後遷移數據:shell

$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  ...
  Applying sessions.0001_initial... OK
複製代碼

準備工做就搞定了。數據庫

用Docker構建項目

初識Docker

Docker 的整個生命週期由三部分組成:鏡像(image)+ 容器(container)+ 倉庫(repository)。

容器是由鏡像實例化而來,這有點像面向對象的概念:鏡像就是類,容器是類實例化以後的對象。

鏡像是一個只讀的模板,它包括了運行容器所需的數據。鏡像能夠包含一個完整的 Linux 操做環境,裏面僅安裝了 Python 或者其餘用戶須要的程序。

容器是由鏡像建立出來的實例,相似虛擬機,裏面能夠運行特定的應用,而且容器與容器是相互隔離的。

倉庫概念與 Git 和 Github 相似,若是你用過它們就很是容易理解。Docker 使用的默認倉庫是由官方維護的 Docker hub 公共倉庫,從中上傳、拉取的操做相似 Git。

目前須要瞭解的就這麼多,下面經過實踐來理解。

Hello-world

爲了確認 Docker 已經正確安裝了,運行如下指令:

$ docker run hello-world

Unable to find image 'hello-world:latest' locally
...
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
...

Hello from Docker!
This message shows that your installation appears to be working correctly.
...
複製代碼

一切正常的話,終端將打印出如上圖所示的歡迎語句。docker run hello-world 指令的含義是:用名稱爲 hello-world 的鏡像構建一個容器並運行。若是本地上沒有這個 hello-world 的鏡像, Docker 會自動從倉庫搜索並下載同名的鏡像。

咱們能夠用 docker images 查看本地已有的鏡像:

$ docker images

REPOSITORY      TAG        IMAGE ID           CREATED           SIZE
hello-world     latest     fce289e99eb9       9 months ago      1.84kB
複製代碼

表列分別爲鏡像名、版本、ID 號、建立時間、大小。

還能夠查看本地已有的容器:

$ docker ps -a

CONTAINER ID   IMAGE        ..   CREATED         ..
38cb03a96dca   hello-world  ..   2 minutes ago   ..
複製代碼

除此以外還有一些很是有用的基礎指令:

docker rmi [images ID]  # 刪除此 ID 的鏡像
docker container stop [container ID]  # 中止此 ID 的容器
docker container start [container ID]  # 啓動此 ID 的容器
docker container rm [container ID]  # 刪除此 ID 的容器
複製代碼

因爲測試時會頻繁生成鏡像,所以你確定會用上面的指令查看、刪除無用的鏡像和容器。

牛刀小試完畢,接下來正式構建 Django 容器。

Dockerfile

Docker 容許經過文本格式的配置文件來構建鏡像,默認名稱爲 Dockerfile。所以在項目根目錄新建文件 Dockerfile,寫入:

# 從倉庫拉取 帶有 python 3.7 的 Linux 環境
FROM python:3.7
 # 設置 python 環境變量
ENV PYTHONUNBUFFERED 1
 # 建立 code 文件夾並將其設置爲工做目錄
RUN mkdir /code
WORKDIR /code
# 更新 pip
RUN pip install pip -U
# 將 requirements.txt 複製到容器的 code 目錄
ADD requirements.txt /code/
# 安裝庫
RUN pip install -r requirements.txt
# 將當前目錄複製到容器的 code 目錄
ADD . /code/
複製代碼

理解這些 Docker 指令的關鍵在於,必定要牢記容器裏的環境和外界**(宿主機)**是隔離的,它兩是徹底不同的。換句話說,要搞清楚哪些操做是針對宿主機、哪些操做是針對容器

FROM python:3.7 指令從倉庫拉取一個包含 python 3.7 的 Linux 操做系統環境(Linux 版本爲 Debian)。

RUNWORKDIR 指令都是針對容器的,功能是在容器裏建立目錄、並將其設置爲工做目錄。注意宿主機是沒有這個目錄的。

ADD 指令出現了兩次。ADD requirements.txt /code/ 意思是將宿主機當前目錄(即 Dockerfile 所在目錄)的 requirements.txt 文件複製到容器的 /code 目錄中。ADD . /code/ 意思是把當前目錄全部內容複製到容器 /code/ 目錄,注意中間那個

目前項目依賴的惟一庫就是 Django,因此在項目根目錄建立 requirements.txt 並寫入:

django==2.2
複製代碼

前面不是已經安裝過 Django 了嗎,爲何這裏還要安裝?緣由是前面是在宿主機安裝的,容器裏是沒有 Django 的!

因此目前的文件結構以下:

django_app
  - Dockerfile
  - requirements.txt
  - manage.py
  - django_app
  - db.sqlite3
複製代碼

配置文件就寫好了,接下來看看 Docker-compose 怎麼用。

Docker-compose

在線上環境中,一般不會將項目的全部組件放到同一個容器中;更好的作法是把每一個獨立的功能裝進單獨的容器,這樣方便複用。好比將 Django 代碼放到容器A,將 Mysql 數據庫放到容器B,以此類推。

所以同一個服務器上有可能會運行着多個容器,若是每次都靠一條條指令去啓動,未免也太繁瑣了。 Docker-compose 就是解決這個問題的,它用來編排多個容器,將啓動容器的命令統一寫到 docker-compose.yml 文件中,之後每次啓動這一組容器時,只須要 docker-compose up 就能夠了。所以教程也會用 docker-compose 來管理容器。

首先確認 docker-compose 是否安裝成功:

$ docker-compose -v
docker-compose version 1.24.1, build 4667896b
複製代碼

確認無誤後,在項目根目錄建立 docker-compose.yml 並寫入:

version: "3"
services:
  app:
    restart: always
    build: .  # '點'表明當前目錄
    command: "python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "8000:8000"
複製代碼

讓咱們來分解一下其中的各項含義。

version 表明 docker-compose.yml 的版本,目前最新版爲 3,不須要改動它。

接着定義了一個名叫 app 的容器。後面的內容都是 app 容器的相關配置:

  • restart :除正常工做外,容器會在任什麼時候候重啓,好比遭遇 bug、進程崩潰、docker 重啓等狀況。
  • build :指定一個包含 Dockerfile 的路徑,並經過此 Dockerfile 來構建容器鏡像。注意那個 "." ,表明當前目錄。
  • command :容器運行時須要執行的命令。這裏就是咱們很熟悉的運行開發服務器了。
  • volumes卷,這是個很重要的概念。前面說過容器是和宿主機徹底隔離的,可是有些時候又須要將其連通;好比咱們開發的 Django 項目代碼經常會更新,而且更新時還依賴如 Git 之類的程序,在容器裏操做就顯得不太方便。因此就有,它定義了宿主機和容器之間的映射:"." 表示宿主機的當前目錄,":" 爲分隔符,"/code" 表示容器中的目錄。即宿主機當前目錄和容器的 /code 目錄是連通的,宿主機當前目錄的 Django 代碼更新時,容器中的 /code 目錄中的代碼也相應的更新了。這有點兒像是在容器上打了一個洞,某種程度上也是實用性隔離性的一種妥協。

嚴格意義上講,這裏用到的 .:/code 並非,而是叫掛載,它兩是有區別的,只不過 docker-compose 容許將掛載寫到卷的配置中。後面章節會講到。

  • ports :定義了宿主機和容器的端口映射。容器的隔離不止環境,甚至連端口都隔離起來了。但 web 應用不經過端口跟外界通訊固然不行,所以這裏定義將宿主機的 8000 端口映射到容器的 8000 端口,即訪問宿主機的 8000 端口就是訪問到了容器的 8000 端口,但要確保端口沒有被其餘程序佔用。

配置就寫好了。如今項目的目錄結構以下:

django_app
  - docker-compose.yml
  - Dockerfile
  - requirements.txt
  - manage.py
  - django_app
  - db.sqlite3
複製代碼

測試

輸入指令 docker-compose up 啓動容器服務:

$ docker-compose up

Creating network "django_app_default" with the default driver
Building app
Step 1/8 : FROM python:3.7
3.7: Pulling from library/python
4a56a430b2ba: Pull complete
...
6933d3d46042: Pull complete
Digest: sha256:0f0e991a97426db345ca7ec59fa911c8ed27ced27c88ae9966b452bcc6438c2f
Status: Downloaded newer image for python:3.7
 ---> 02d2bb146b3b
Step 1/8 : FROM python:3.7
 ---> 02d2bb146b3b
...
Step 7/8 : RUN pip install -r requirements.txt
 ---> Running in 62a60a3003fe
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting django==2.2 (from -r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/54/85/0bef63668fb170888c1a2970ec897d4528d6072f32dee27653381a332642/Django-2.2-py3-none-any.whl (7.4MB)
...
Installing collected packages: sqlparse, pytz, django
Successfully installed django-2.2 pytz-2019.2 sqlparse-0.3.0
...
Step 8/8 : ADD . /code/
 ---> cb23f483ffb6
Successfully built cb23f483ffb6
Successfully tagged django_app_app:latest
WARNING: Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating django_app_app_1 ... done
Attaching to django_app_app_1
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 05, 2019 - 15:03:15
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.
複製代碼

能夠看到 Docker 按照配置文件的要求,成功構建了鏡像及容器,並啓動了容器。

打開瀏覽器,輸入本地 IP 端口 127.0.0.1:8000

看到 Django 的小火箭,項目成功運行起來啦。按 Ctrl + C 便可中止開發服務器運行。

中止服務器後實際上容器還存在,只是中止運行了而已。輸入:

$ docker-compose down
複製代碼

就能夠刪除容器。

若是想在後臺運行容器,則輸入:

$ docker-compose up -d
複製代碼

另外,若是你須要從新構建鏡像,則輸入命令:

$ docker-compose build
複製代碼

啓動和中止已有的容器:

$ docker-compose start
$ docker-compose stop
複製代碼

很簡單吧。

下載太慢?

因爲衆所周知的緣由,國內的網絡環境很是複雜。在構建鏡像時常常須要從國外的遠程倉庫拉取資源,巋然不動的下載速度真的頭疼。

解決方法就是將資源拉取連接修改成國內的鏡像源,好比清華的鏡像源。

修改 Dockerfile 以下:

FROM python:3.7
ENV PYTHONUNBUFFERED 1
 # 添加 Debian 清華鏡像源
RUN echo \
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free\
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free\
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free\
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free\
    > /etc/apt/sources.list

RUN mkdir /code
WORKDIR /code
# 添加 pip 清華鏡像源
RUN pip install pip -U -i https://pypi.tuna.tsinghua.edu.cn/simple
ADD requirements.txt /code/
# 添加 pip 清華鏡像源
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
ADD . /code/
複製代碼

從新構建鏡像,下載速度就飛同樣快了。

教程後面的內容都使用了清華源,但爲了方便閱讀,把這一部分更換源的代碼省去了,讀者內心明白就好。

總結

本章初步感覺了 Docker 的工做流程,而且很輕鬆的構建了一個容器化的 Django 項目。

下一章將 MySQL 數據庫也加入到容器編排中。


相關文章
相關標籤/搜索