docker简介
目的:可以简单理解为开发人员干了运维的活,开发人员在自己的机器上可以跑,发给运维后,运维却跑不起来。
原因:运维在自己的机器上没有相应的环境和配置。
解决:开发人员将项目的源码以及相对应的环境和配置一起打包给运维。
以上这个流程大概就是docker所做的事情。
在简单一点理解,比如,去鱼店买了一条金鱼,带回家后自己养就死了。那直接把鱼店的水,水草,装饰等一起带回家,就可以养活。
docker简单理解为:一个微量的Linux系统。大概170M左右把,VM虚拟机都4G差不多。
docker三大概念:
镜像:保存在仓库中,比如nginx镜像,redis镜像。
容器:是一个个的镜像实例。相当于一个简易版的Linux环境。
仓库:保存各种镜像,需要的时候直接去拉取。相当于github一样。
简单理解:
容器相当于类,镜像相当于类的实例对象。
总结:
我们把应用程序和项目依赖配置打包形成一个完整的运行环境,这个打包好的运行环境就可以看作是一个镜像文件。只有通过这个镜像文件才能生成Docker容器。镜像文件可以看作是容器的模板。Docker根据镜像文件生成容器的实例。同一个镜像文件,可以生成多个同时在运行的容器实例。
创建Django项目
在Linux终端中
1.安装Django库
$ pip install django==2.2
2.在一个你喜欢得位置(比如/home/)创建新的 Django 项目
$ django-admin startproject django_app
3.进入项目根目录:
$ cd django_app
注:后面的所有内容全部都在此目录中操作!
4.迁移数据
$ python manage.py migrate
####用Docker构建项目
1.首先确认安装好了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.
2.docker images 查看本地已有的镜像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 9 months ago 1.84kB
3.查看本地已有的容器:
$ docker ps -a
CONTAINER ID IMAGE .. CREATED ..
38cb03a96dca hello-world .. 2 minutes ago ..
4.其他基础命令:
docker rmi [images ID] # 删除此 ID 的镜像
docker container stop [container ID] # 停止此 ID 的容器
docker container start [container ID] # 启动此 ID 的容器
docker container rm [container ID] # 删除此 ID 的容器
Dockerfile
以下正式开始构建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/
目前项目依赖的唯一库就是 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"
配置就写好了。现在项目的目录结构如下:
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 :
下载太慢?
由于众所周知的原因,国内的网络环境非常复杂。在构建镜像时经常需要从国外的远程仓库拉取资源,岿然不动的下载速度真的头疼。
解决方法就是将资源拉取链接修改为国内的镜像源,比如清华的镜像源。
修改 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/s
Django-Docker容器化部署:Django-Docker-MySQL部署
上面我们成功搭建了容器化的 Django 项目,用到的数据库为默认的 Sqlite。Sqlite 虽然简单易用,但是线上部署时通常会选择更高效、更可靠的数据库,比如 MySQL。
本例使用两个容器:
名称叫 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
接下来修改 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/
其他配置
修改 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': '123456',
'HOST': 'db',
'PORT': '3306',
}
}
测试
测试之前,请先确认没有其他程序占用了 3306 端口,比如宿主机安装的 MySQL。
重新生成镜像:
$ docker-compose build
生成并启动容器:
$ docker-compose up
打开浏览器访问 127.0.0.1:8000
Django-Docker容器化部署:Django-Docker-MySQL-Nginx-Gunicorn云端部署
上面我们实现了在 Docker 中添加了 MySQL 数据库,但采用的开发服务器虽然使用便捷,但性能差、可靠性低,无法应用在生产环境中。
本节将实现 Docker + Django + MySQL + Nginx + Gunicorn 容器项目,完成最终的服务器部署。
Docker-compose
在部署到服务器之前,先来尝试本地部署。
在上一章的基础上,继续修改 docker-compose.yml 配置:
version: "3"
services:
app:
restart: always
build: .
command: bash -c "python3 manage.py collectstatic --no-input && python3 manage.py migrate && gunicorn --timeout=30 --workers=4 --bind :8000 django_app.wsgi:application"
volumes:
- .:/code
- static-volume:/code/collected_static
expose:
- "8000"
depends_on:
- db
networks:
- web_network
- db_network
db:
image: mysql:5.7
volumes:
- "./mysql:/var/lib/mysql"
ports:
- "3306:3306"
restart: always
environment:
- MYSQL_ROOT_PASSWORD=mypassword
- MYSQL_DATABASE=django_app
networks:
- db_network
nginx:
restart: always
image: nginx:latest
ports:
- "8000:8000"
volumes:
- static-volume:/code/collected_static
- ./config/nginx:/etc/nginx/conf.d
depends_on:
- app
networks:
- web_network
networks:
web_network:
driver: bridge
db_network:
driver: bridge
volumes:
static-volume:
其他配置
首先修改 Nginx 的配置文件,即映射到 nginx 容器的 config/nginx/django_app.conf :
upstream app {
ip_hash;
server app:8000;
}
server {
listen 8000;
server_name localhost;
location /static/ {
autoindex on;
alias /code/collected_static/;
}
location / {
proxy_pass http://app/;
}
}
此配置下 Nginx 会监听容器的 8000 端口,并将收到的请求发送到 app 容器(静态文件请求除外)。
在 requirements.txt 文件中增加 gunicorn 库:
django==2.2
mysqlclient==1.3.14
gunicorn==19.9.0
最后修改 django_app/settings.py 的域和静态文件存放目录的配置:
...
ALLOWED_HOSTS = ['*']
...
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
STATIC_URL = '/static/'
所有配置就完成了
测试
测试指令就一条:$ docker-compose up
浏览器访问 127.0.0.1:8000
本地部署成功,下一步服务器部署。
服务器部署
有了本地部署的经验,服务器部署就非常非常简单了。
还是类似的,部署前将 Docker 、 Docker-compose 、 Python3 等工具在服务器上安装好;将项目用 Git 克隆到服务器本地。
接下来把 settings.py、config/nginx/django_app.conf、requirements.txt 相关位置都按教程流程改好;将 docker-compose.yml 和 Dockerfile 复制到服务器。
由于 http 请求默认为 80 端口,所以为了接收公网请求,还需要做一点点修改 docker-compose.yml 的工作:
version: "3"
services:
app:
...
command: bash -c "... your_project_name.wsgi:application" # 改为你的项目名称
...
db:
...
nginx:
...
ports:
- "80:8000" # 监听 80 端口
...
networks:
...
volumes:
...
修改 Gunicorn 绑定的项目名称,以及让宿主机监听公网 http 默认的 80 端口。
此外还要修改 config/nginx/django_app.conf :
upstream your_domain_name {
ip_hash;
server app:8000;
}
server {
...
location / {
proxy_pass http://your_domain_name/;
}
}
最后,记得将 settings.py 中的 DEBUG 配置修改好:
# DEBUG=True 注释掉
DEBUG=False
这样就可以了!构建镜像并启动容器:
$ docker-compose up
在浏览器中就可以正常访问你的网站了。