文章目录
centos7用docker-compose部署nginx、mysql、django
1. 前期准备
想体验一下docker的便利,遂在本机用docker部署自己的django项目
准备:vmware虚拟机 + centos 7系统
1.1 docker安装
- 更新yum包
sudo yum update
- 安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
- 设置yum源
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
- 可以查看所有仓库中所有docker版本,并选择特定版本安装
yum list docker-ce --showduplicates | sort -r
- 安装docker
sudo yum install docker-ce #由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0
- 启动并加入开机启动
sudo systemctl start docker
sudo systemctl enable docker
- 验证安装是否成功(有client和service两部分表示docker安装启动都成功了)
docker version
链接1
1.2 docker-compose 安装
- 方法一:(网络原因经常失败,或者速度很慢)
curl -L https://get.daocloud.io/docker/compose/releases/download/2.28.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# 若上面的链接失效,则使用该链接
curl -L https://github.com/docker/compose/releases/download/v2.28.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# 权限
sudo chmod +x /usr/local/bin/docker-compose
# 确认是否安装成功
docker-compose -v
-
方法二:
-
安装python-pip
yum -y install epel-release
yum -y install python-pip
-
安装docker-compose
pip install docker-compose
待安装完成后,执行查询版本的命令
docker-compose version
-
1.3 路径及代码准备
mkdir /data/
mkdir /data/django_code
接着把已有的django项目内容整个拷贝到django_code路径下,结构如下
django_code
- Dockerfile
- requirements.txt
- manage.py
- myproject # 项目
- myapp # 项目下的app
- appfront # 前端代码
(Dockerfile以及requirements.txt后面会讲)
1.3.1 nginx配置文件
新建nginx的配置文件,放在/data/config/nginx/下。
后面会映射到 nginx 容器的 config/nginx/django_app.conf :
upstream app {
# "app" (domain_name)
ip_hash;
server app:8000; # "app" docker_server_name
}
server {
listen 8000;
server_name localhost;
location /static/ {
autoindex on;
alias /code/appfront/dist/static/;
}
location / {
proxy_pass http://app/;
# "app" (domain_name)
}
}
domain_name这个改动主要是为了照顾各种第三方登录的回调地址(不改这里, GitHub、Weibo 三方登录都会失败)。如果你没有类似的需求,不改也是可以的。比如个人网站是 www.betterhy.com
,所以这里的 domain_name
就修改为 www.betterhy.com
。
1.3.2 requirements.txt
# 在项目根目录(这个文件通常在最外层)执行,可将所需库输入到文件中
pip freeze > requirements.txt
# 或者自己根据项目,手动添加进去
这里贴一下个人的依赖库
Django==2.1.2
django-cors-headers==2.4.0
django-extensions==2.2.1
django-redis==4.10.0
django-secure==1.0.1
django-sslserver==0.20
django-werkzeug-debugger-runserver==0.3.1
mysqlclient==1.3.13
Pillow==5.3.0
requests==2.21.0
wechatpy==1.8.5
cryptography==2.9.2
gunicorn==19.9.0
至此前期准备完成
2. Dockerfile
Docker 允许通过文本格式的配置文件来构建镜像,默认名称为 Dockerfile。因此在项目根目录新建文件Dockerfile,写入:
# 从仓库拉取 带有 python 3.7 的 Linux 环境
FROM python:3.7
# 设置 python 环境变量
ENV PYTHONUNBUFFERED 1
# RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
# 或者
# 添加 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 apt-get clean
# RUN apt-get update
# 以下两项如果安装太慢,该步可暂缓
# RUN apt-get install -y mysql-client
# RUN apt-get install python3-dev default-libmysqlclient-dev -y
# 创建 code 文件夹并将其设置为工作目录
RUN mkdir /code
WORKDIR /code
# 更新 pip
RUN pip install pip -U -i https://pypi.tuna.tsinghua.edu.cn/simple
# 将 requirements.txt 复制到容器的 code 目录
ADD requirements.txt /code/
# 安装库
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 将当前目录复制到容器的 code 目录
ADD . /code/
# RUN server after docker is up
# CMD ./start.sh
# RUN python manage.py runserver 0.0.0.0:8000
3. 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 myproject.wsgi:application"
volumes:
- .:/code
- static-volume:/code/appfront/dist/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=123456
- MYSQL_DATABASE=rainrose
networks:
- db_network
nginx:
restart: always
image: nginx:latest
ports:
- "8000:8000"
# 这里可以修改为80:8000,这样访问机器的时候就可以不用加端口号访问,因为浏览器默认访问80端口
volumes:
- static-volume:/code/appfront/dist/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:
先单解析一下app配置
这里定义了一个名叫 app
的容器。后面的内容都是 app
容器的相关配置:
restart
:除正常工作外,容器会在任何时候重启,比如遭遇 bug、进程崩溃、docker 重启等情况。build
:指定一个包含 Dockerfile 的路径,并通过此 Dockerfile 来构建容器镜像。注意那个 “.” ,代表当前目录。command
:容器运行时需要执行的命令。这里就是我们很熟悉的运行开发服务器了。volumes
:卷,这是个很重要的概念。前面说过容器是和宿主机完全隔离的,但是有些时候又需要将其连通;比如我们开发的 Django 项目代码常常会更新,并且更新时还依赖如 Git 之类的程序,在容器里操作就显得不太方便。所以就有卷,它定义了宿主机和容器之间的映射:“.” 表示宿主机的当前目录,“:” 为分隔符,“/code” 表示容器中的目录。即宿主机当前目录和容器的 /code 目录是连通的,宿主机当前目录的 Django 代码更新时,容器中的 /code 目录中的代码也相应的更新了。这有点儿像是在容器上打了一个洞,某种程度上也是实用性和隔离性的一种妥协。
严格意义上讲,这里用到的
.:/code
并不是卷,而是叫挂载,它两是有区别的,只不过 docker-compose 允许将挂载写到卷的配置中。后面章节会讲到。
配置大体解析:
- 定义了 3 个容器,分别是
app
、db
和nginx
。容器之间通过定义的端口进行通讯。 - 定义了 2 个网络,分别是
web_network
和db_network
。只有处在相同网络的容器才能互相通讯。不同网络之间是隔离的,即便采用同样的端口,也无法通讯。 - 定义了 1 个数据卷,
static-volume
。数据卷非常适合多个容器共享使用同一数据,你可以看到app
和nginx
都用到了它。 expose
和ports
都可以暴露容器的端口,区别是 expose 仅暴露给其他容器,而 ports 会暴露给其他容器和宿主机。
3.1 网络 network
Docker 允许用户给每个容器定义其工作的网络,只有在相同的网络之中才能进行通讯。你可以看到 nginx
容器处于 web_network
网络,而 db
容器处于 db_network
网络,因此它两是无法通讯的,实际上确实也不需要通讯。而 app
容器同时处于 web_network
和 db_network
网络,相当于是桥梁,连通了3个容器。
定义网络可以隔离容器的网络环境,也方便运维人员一眼看出网络的逻辑关系。
3.2 数据卷
前面我们见识过的用于映射宿主机和容器目录的卷了,实际上称为挂载;现在新出现的 static-volume
才叫卷。它的使用方式像这样:static-volume:/code/appfront/dist/static
,冒号后面还是容器内的目录,但冒号前的却不是宿主机目录、仅仅是卷的名称而已。从本质上讲,数据卷也是实现了宿主机和容器的目录映射,但是数据卷是由 Docker 进行管理的,你甚至都不需要知道数据卷保存在宿主机的具体位置。
相比挂载,数据卷的优点是由于是 Docker 统一管理的,不存在由于权限不够引发的挂载问题,也不需要在不同服务器指定不同的路径;缺点是它不太适合单配置文件的映射。
和挂载一样,数据卷的生命周期脱离了容器,删除容器之后卷还是存在的。下次构建镜像时,指定卷的名称就可以继续使用了。
数据卷有个很重要的特性:启动时如果卷是空的,则会将容器映射目录的所有内容复制到卷里去。换句话说就是,只要卷初始化完成后,容器原始的 collected_static
目录就不会再使用了,新增的文件也只存在于卷中,容器中是没有的。
实际上 static 静态文件(以及 media 媒体文件)的持久存储,通过挂载或者数据卷都可以实现;具体用哪种,这个就见仁见智了,你自己选择。
4. 构建并启动容器(这个过程可能出现各种问题)
docker-compose up
当出现问题时候就用docker logs id命令查看对应id容器的日志,解决问题
若拉取镜像出现速度慢的问题,这时候使用阿里云Docker加速 阿里云容器镜像服务地址
配置镜像加速器:
针对Docker客户端版本大于 1.10.0 的用户
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
5. 其他(部署过程中我自己遇到过的一些坑0.0)
5.1 一些命令
docker ps #查看所有运行中的容器
docker ps -a# 查看所有的运行过的容器
docker exec -it id /bin/bash #进入指定id容器
docker stop id #停止容器运行 (id可输前几位,能确定到某一容器即可)
docker start id #运行容器
docker rm id #删除容器
docker images #查看镜像
docker rmi images #删除镜像
5.2 错误太多,导致构建太多次,然后空间不够用
docker image prune -a # 删除未使用到的镜像
docker image prune -a -f #-f强制,不需要确认
包括上述的删除镜像指令,自行斟酌
5.3 docker-compose生成命令以及它们的区别
-
以下仅生成image,构建image,不启动容器(只生成image,不启动):
docker-compose build
-
如果image不存在,则以下将构建image并启动容器(可能不生成image,然后启动):
docker-compose up
它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。链接的服务都将会被自动启动,除非已经处于运行状态。
选项:
-
-d 在后台运行服务容器
-
–no-color 不使用颜色来区分不同的服务的控制台输出
-
–no-deps 不启动服务所链接的容器
-
–force-recreate 强制重新创建容器,不能与–no-recreate同时使用
-
–no-recreate 如果容器已经存在了,则不重新创建,不能与 –force-recreate 同时使用
-
–no-build不自动构建缺失的服务镜像
-
-t,–timeout TIMEOUT 停止容器时候的超时(默认为10秒)
-
–build 则即使不需要时,也会强制生成image(重新生成image,然后启动)
-
5.4 docker-compose在dockerfile更新后自动更新image
docker-compose stop
docker-compose up -d --build
5.5 解决docker启动错误 error creating overlay mount to /var/lib/docker/overlay2
最近在centos7.1使用docker运行redis镜像,出现下面的错误:
/usr/bin/docker-current: Error response from daemon: error creating overlay mount to /var/lib/docker/overlay2/65f3c109fb903539820f84856d2725af784f2f03f95b1f0214e34184e4d61ff7-init/merged: invalid argument.
See '/usr/bin/docker-current run --help'.
在网上搜索一番后,一个可行的方案如下(改变storage driver类型, 禁用selinux):
停止docker服务
systemctl stop docker
清理镜像
rm -rf /var/lib/docker
修改存储类型
vi /etc/sysconfig/docker-storage
把空的DOCKER_STORAGE_OPTIONS参数改为overlay:
DOCKER_STORAGE_OPTIONS="--storage-driver overlay"
禁用selinux
vi /etc/sysconfig/docker
去掉option的–selinux-enabled
启动docker应该就可以了
systemctl start docker
5.6 路径文件权限问题
这时候需要禁用centos的SELinux
-
查看SELinux的状态:
/usr/sbin/sestatus -v | grep SELinux
-
关闭:
vi /etc/selinux/config
SELINUX=enforcing改为SELINUX=disabled
重启生效
配置说明的部分参照:Django-Docker容器化部署:Django-Docker本地部署