centos7用docker-compose部署nginx、mysql、django
1. 前期准备
想体验一下docker的便利,遂在本机用docker部署自己的django项目
准备:vmware虚拟机 + centos 7系统
1.1 docker安装
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
- 启动并加入开机启动
sudo systemctl start docker
sudo systemctl enable docker
- 验证安装是否成功(有client和service两部分表示docker安装启动都成功了)
docker version
链接
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 {
ip_hash;
server app:8000;
}
server {
listen 8000;
server_name localhost;
location /static/ {
autoindex on;
alias /code/appfront/dist/static/;
}
location / {
proxy_pass http://app/;
}
}
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
FROM python:3.7
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
RUN pip install pip -U -i https://pypi.tuna.tsinghua.edu.cn/simple
ADD requirements.txt /code/
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
ADD . /code/
3. Docker-compose
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"
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 目录中的代码也相应的更新了。这有点儿像是在容器上打了一个洞,某种程度上也是实用性和隔离性的一种妥协。
配置大体解析:
- 定义了 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 数据卷
相比挂载,数据卷的优点是由于是 Docker 统一管理的,不存在由于权限不够引发的挂载问题,也不需要在不同服务器指定不同的路径;缺点是它不太适合单配置文件的映射。
和挂载一样,数据卷的生命周期脱离了容器,删除容器之后卷还是存在的。下次构建镜像时,指定卷的名称就可以继续使用了。
实际上 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
最近在.1使用运行镜像,出现下面的错误:
/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类型, 禁用):
停止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
重启生效
配置说明的部分参照: