本文章爲原創內容,只發佈於本博客和 我的私人博客,轉載請註明,謝謝
項目源碼,歡迎 Fork 和 Star | 本人 Django 博客預覽
基於 Docker 的 Django 容器化部署教程分爲三部分,當前所在的是第一部分
- 基於 Docker 的 Django 容器化部署之一:定製屬於自己的 docker 鏡像
- 基於 Docker 的 Django 容器化部署之二:docker-compose 部署 Django 項目
- 基於 Docker 的 Django 容器化部署之三:定時備份,兩步實現服務器遷移
項目部署一直都是很繁瑣的事情,由於開發環境和上線服務器的環境不同,所以各種依賴軟件包的安裝、迭代更新的部署、各種命令的執行都是問題,由此容器化進行項目上線就是一個很好的解決辦法。
本次使用的是 Docker
,屬於 Linux 容器
的一種封裝,提供簡單易用的容器使用接口。docker
將應用程序與該程序的依賴打包到一個文件裏面,運行這個文件,就會生成一個輕量級、可移植的虛擬容器,然後發佈到任何流行的 Linux 或 Windows 機器上,程序在這個虛擬容器裏面運行就像在真實的物理機上面運行一樣。這種容器技術,可以爲我們提供一個隔離的運行環境,並且只提供我們所需要的內容。
瞭解 docker 及 docker-compose
Docker
Docker
的整個生命週期由三部分組成:鏡像(image)
+ 容器(container)
+ 倉庫(repository)
。
Docker
可以生成多個鏡像,每個鏡像,可以創建多個容器。可以理解成:每一個容器都是一個獨立的虛擬操作系統,互不影響,而鏡像就是這個操作系統的安裝包。想要生成一個容器,就要用安裝包(鏡像)生成一次,這就是 Docker
的核心概念。發佈到倉庫(比如 DockerHub
)時,是以鏡像爲單位。
- 鏡像,是一個只讀的模板,一個獨立的文件系統,包括運行容器所需的數據,可以用來創建新的容器。鏡像可以包含一個完整的
Linux
操作環境,裏面僅安裝了Python
或者其他用戶需要的程序。
-
容器,是由鏡像實例化而來,容器是基於鏡像創建的,即容器中的進程依賴於鏡像中的文件,類似虛擬機,裏面可以運行特定的應用,並且容器與容器是相互隔離的。這有點像面向對象的概念:鏡像就是類,容器是類實例化之後的對象。
-
倉庫,與
Git
和Github
類似,Docker
使用的默認倉庫是由官方維護的Docker hub
公共倉庫,此倉庫是用來包含鏡像的位置,同時其還提供了一個註冊服務器(register)來保存多個倉庫,每個倉庫又可以包含多個具備不同tag
的鏡像,而倉庫支持的操作如上傳、拉取等動作類似於Git
。
docker-compose
Docker Compose
是 docker
提供的一個命令行工具,用來定義和運行由多個容器組成的應用。使用 compose,我們可以通過 YAML
文件聲明式的定義應用程序的各個服務,並由單個命令完成應用的創建和啓動。簡單來說,就是用來編排多個容器,將啓動容器的命令統一寫到 docker-compose.yml
文件中,一次啓動全部啓動。
安裝 docker 及 docker-compose
- 參考 centos7 安裝docker-ce和docker-compose
- 參考 Debian9 安裝docker-ce和docker-compose
- 參考 Github Actions:雲打包創建 docker 鏡像
基於 Dockerfile 構建鏡像
打包鏡像,就要用到一個文本文件,這個文本默認名稱就是 Dockerfile
.
鏡像構建的過程中有一個非常重要的概念就是分層構建,前一層是後一層的基礎。每一層構建完就不會再發生改變,後一層上的任何改變只發生在自己這一層。比如,刪除前一層文件的操作,實際不是真的刪除前一層的文件,而是僅在當前層標記爲該文件已刪除。在最終容器運行的時候,雖然不會看到這個文件,但是實際上該文件會一直跟隨鏡像。
先來看一下我的目錄結構,這樣子編排是因爲後面要使用 docker-compose
.
├── django
├── docker-compose.yml
└── nginx
在項目的根目錄下新建一個 Dockerfile
文件,無後綴,寫入下面內容
# 從倉庫拉取 python 官方的 image,:3.7就是標籤,代表是 3.7 版本的 python 鏡像
FROM python:3.7
# 作者信息
LABEL "author"="HONGWEI"
LABEL "blog"="https://www.zhwei.cn/"
LABEL "E-mail"="[email protected]"
# 設置 python 環境變量
ENV PYTHONUNBUFFERED 1
# 構建參數
## 定義存放本機中的 django 項目的目錄
ARG work_dir=/opt/hw-blog
# 在鏡像中創建目錄並設置項目運行的工作目錄
RUN mkdir -p ${work_dir}
WORKDIR ${work_dir}
# 將 django 的源碼複製到容器的工作目錄,其中requirements.txt在裏面
ADD ./django ${work_dir}
# 安裝依賴包
RUN pip install -r requirements.txt
構建鏡像
docker build -t hw-website .
構建完之後查看一下docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hw-website latest 4ff*****1cae About a minute ago 1.06GB
定製屬於自己的 docker 鏡像
當你以上面的方式進行打包鏡像的時候你會發現鏡像的體積很大,並且裏面有好多包是我們不需要的
- Centos 的 Python 3.7 的鏡像 900M+,包含python2
- Ubuntu 的 Python 3.7 的鏡像 800M+,
- Python:3.7-alpine 鏡像 90M+,但好多東西沒有,需要自己構建
所以我們就要進行自己定製,裏面只有我需要的
Dockerfile
# 從倉庫拉取 帶有 python 3.7 的 Alpine Linux 環境
FROM python:3.7-alpine
# 作者信息
LABEL "author"="HONGWEI"
LABEL "blog"="https://www.zhwei.cn/"
LABEL "E-mail"="[email protected]"
# 構建參數,工作目錄
ARG work_dir=/opt/hw-blog
RUN mkdir -p ${work_dir}
WORKDIR ${work_dir}
# 將當前目錄複製到容器的工作目錄
ADD ./django ${work_dir}
# 安裝alpine依賴, system update\ mysqlclient\ system lib\ Pillow\ bash
RUN apk update \
&& apk add --virtual mysqlclient-build gcc python3-dev musl-dev \
&& apk add --no-cache mariadb-dev \
&& apk add --virtual system-build linux-headers libffi-dev \
&& apk add --no-cache jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
&& apk add --no-cache bash bash-doc bash-completion \
&& pip install pip -U \
&& pip install -r ${work_dir}/requirements.txt
# 在Alpine上,pip將從源代碼構建需要依賴包來install,如mysqlclient需要gcc和musl-dev,因此需要將apk del *-build推遲到安裝Python模塊之後
RUN apk del mysqlclient-build \
&& apk del system-build
構建鏡像
docker build -t hw-website .
構建完之後查看一下docker images
,效果立杆見影
REPOSITORY TAG IMAGE ID CREATED SIZE
hw-website latest 14a*****6c5a 12 minutes ago 549MB
依賴包說明:
python:3.7-alpine
:alpine
是一個Linux
系統發行版,主打小巧、輕量、安全。我們程序運行需要Python
環境,因此使用這個小巧但包含完整 Python 環境的基礎鏡像來構建我們的應用鏡像。mysqlclient
:我使用的是mysql
數據庫。編譯所需的庫文件在pypi
上可以查到 mysqlclient依賴庫Pillow
:使用django
處理圖片時,會使用到Pillow
這個Python
庫。Pillow依賴庫
所以至於你需要的其他庫的依賴,需要去搜索一下
小技巧
- 添加alpine apk源
參考 Alpine Linux package management 和 alpine-mirrors/mirrors.yaml
# 添加alpine apk源
RUN echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories;
RUN echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories;
RUN echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/latest-stable/main/" >> /etc/apk/repositories;
RUN echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/latest-stable/community/" >> /etc/apk/repositories;
RUN echo "http://dl-cdn.alpinelinux.org/alpine/latest-stable/community/" >> /etc/apk/repositories;
RUN echo "http://dl-2.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories;
RUN echo "http://dl-3.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories;
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories;
RUN echo "http://dl-5.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
- 添加豆瓣
pip
源
# 構建參數,pip源
ARG pip_url=https://pypi.douban.com/simple
ARG pip_host=pypi.douban.com
# 更新 pip 到最新
RUN pip install pip -U -i ${pip_url}
# 將本地的文件拷貝到容器鏡像
COPY requirements.txt /requirements.txt
# pip 安裝依賴文件
RUN pip install -r requirements.txt -i ${pip_url} --trusted-host ${pip_host}
好了,問題來了
鏡像我都構建完了,怎麼用呢?
請看下一篇 基於 Docker 的 Django 容器化部署之二:docker-compose 部署 Django 項目