若出现一些安装失败的现象可以试一下更新软件包
yum -y install yum-utils
yum -y install docker
yum -y install docker-compose
yum -y install docker-compose-plugin #使用compose前必装
开启docker测试一下,出现版本号即成功
systemctl start docker
docker version
# 开机自启
systemctl enable docker
因为外网链接比较慢,所以配置一个国内镜像会好很多,我们登录阿里云控制台,弹性计算下的容器服务点进去,选择镜像工具
配置加速器:
sudo mkdir -p /etc/docker #创建一个配置文件夹
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://l7twb7ux.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload #重新加载所有单元文件
sudo systemctl restart docker #重启docker
docker的一些常用用法
# 从远程库搜索镜像
docker search 镜像名字
# 拉取镜像
docker pull 镜像名字
# 启动hello-world镜像,会先本地搜索,再远程搜索
docker run hello-world
#查看镜像
docker images
# 查看全部容器
docker ps -a
# 查看正在运行的容器
dcoker ps
# 删除容器或镜像
docker rm 容器ID/名字
docker rmi 镜像ID/名字
# 进入容器伪终端
docker exec -it 容器ID /bin/bash
# 构建镜像
docker compose build
# 用当前目录配置的docker-compose.yml运行/关闭容器,若还没构建镜像会先构建镜像
docker compose up/down
# 后台运行
docker-compose up -d
# 启动其中一个容器
docker-compose up -d 容器名字/ID
# 若不使用默认的docker-compose.yml 文件名:
docker compose -f server.yml up -d
注意:使用yum安装的git在/usr/bin/git下
yum -y install git
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
#查看配置是否生效
git config --list
我们直接使用最常用的docker-compose配置部署多容器程序,使用docker-compose部署需要两个配置文件
Dockerfile和docker-compose.yml
Dockerfile是关于构建镜像的问题
docker-compose.yml里面是关于容器的编排,网络,挂载等
# 从仓库拉取一个包含 python 3.7 的 Linux 操作系统环境(Linux 版本为 Debian)。
FROM python:3.7
# 设置 python 环境变量
ENV PYTHONUNBUFFERED 1
# 这两行是在系统钟安装了MySQL的连接器
# updata太慢 设置镜像源
RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& apt-get clean \
&& apt-get update \
&& apt-get install python3-dev default-libmysqlclient-dev -y
# 创建 code 文件夹并将其设置为工作目录
RUN mkdir /code
WORKDIR /code
# 将 requirements.txt 复制到容器的 code 目录
ADD requirements.txt /code/
# 换源 更新pip并安装依赖库
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && pip install pip -U && pip install -r requirements.txt
# 将当前目录复制到容器的 code 目录
ADD . /code/
这里两个点讲一下
1.尽量减少一个Dockerfile中的RUN命令的个数
RUN命令在构建时会创建一个新层,如非特殊的需要,建议一个Dockerfile在需要使用RUN命令的时候尽可能的只用一个RUN命令,将多条RUN命令进行合并可以有效降低构建的镜像的层数。
2.使用&&连接多条命令
出错之后就地返回是Dockerfile中进行错误控制的一条经验,这样不但能快速定位到错误的地方,还能出错时减少镜像构建的时间。在RUN命令中如果需要使用多条语句,建议使用&&进行连接,单条语句结束时使用 \进行连接避免可读性太差。使用全部使用&&符的好处在于如果出错后续的内容就会不再执行,在镜像构建失败的时候根据出错的第一现场能更加容易地快速确认问题的原因。
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/static
expose:
- "8000"
depends_on:
- db
- chrome
networks:
- web_network
- db_network
db:
image: mysql:5.7
volumes:
- "./mysql:/var/lib/mysql"
ports:
- "3306:3306"
restart: always
command: "mysqld --user=root --explicit_defaults_for_timestamp --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci"
environment:
- MYSQL_ROOT_PASSWORD=数据库密码
- MYSQL_DATABASE=数据库名称
networks:
- db_network
chrome:
image: selenium/node-chrome:4.3.0-20220726
shm_size: 2gb
restart: always
shm_size: 2gb # 容器的共享内存,太小会运行不了,据说2GB效果好,测试1GB也能跑
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub # 事务总线端口,与Hub容器名一致
- SE_EVENT_BUS_PUBLISH_PORT=4442 # 浏览器事务发布端口
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443 # 浏览器事务订阅端口
networks:
- db_network
selenium-hub:
image: selenium/hub:4.3.0-20220726
container_name: selenium-hub # 设定容器名字,与脚本中对应,在其他项目使用时记得换
restart: always
ports:
- "8000:4444" # 可以查看浏览器状态
networks:
- db_network
nginx:
restart: always
image: nginx:latest
ports:
- "80:8000"
volumes:
- static-volume:/code/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:
从整体上看,我们定义了5个容器,分别是app、db、nginx、Chrome和selenium-hub,容器之间通过定义的端口进行通讯。定义了两个网络,分别是web_network和db_network,只有处在同一网络下的容器才能够互相通讯
。不同网络之间是隔离的,即便采用同样的端口,也无法通讯。定义了一个数据卷static-volume。数据卷非常适合多个容器共享使用同一数据
,可以看到app和nginx都使用到了它。expose和ports都可以暴露容器的端口,区别是expose仅暴露给其他容器,而ports会暴露给其他容器和宿主机
。
看一下一些基本的语句意思
restart
:除正常工作外,容器会在任何时候重启,比如遭遇 bug、进程崩溃、docker 重启等情况。command
:容器运行时需要执行的命令。volumes
:数据卷。前面说过容器是和宿主机完全隔离的,但是我们开发的 Django 项目代码常常会更新,并且更新时还依赖如 Git 之类的程序,在容器里操作就显得不太方便。所以就有卷,它定义了宿主机和容器之间的映射:".
" 表示宿主机的当前目录,":
" 为分隔符,"/code
" 表示容器中的目录。即宿主机当前目录和容器的 /code 目录是连通的,宿主机当前目录的 Django 代码更新时,容器中的 /code 目录中的代码也相应的更新了。这里用到的 .:/code
并不是卷,而是叫挂载,docker-compose 允许将挂载写到卷的配置中。expose
:暴露容器的8000端口供其他容器访问,宿主机和外界无法访问ports
:"80:8000
"这句是将容器内的8000端口映射到宿主机的80端口供外界访问networks
:能够访问web_network和db_networkdepends_on
:意思是此容器需要等待 db 容器启动完毕才能够启动。image
:从仓库拉取对应的镜像environment
:定义容器的环境变量,例如设置了MySQL 的 root 用户的密码、数据库的名称。command中的
gunicorn --timeout=30 --workers=4 --bind :8000 django_app.wsgi:application
使用gunicorn的一些启动配置,设置超时为30秒,4个线程,绑定容器8000,django_app.wsgi:application就是你django应用下wsgi.py中的application
- static-volume:/code/static
是容器数据卷,不是挂载,由Docker自己管理
python3 manage.py collectstatic --no-input
收集静态文件,需要在settings.py中设置一下
ALLOWED_HOSTS = ['*']
...
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
STATIC_URL = '/static/'
- "./mysql:/var/lib/mysql"
将MySQL中的数据挂载到宿主机的mysql文件夹,实现持久化储存
"mysqld --user=root --explicit_defaults_for_timestamp --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci"
这个命令是设置与MYSQL容器数据库的字符集,因为默认创建的数据库字符集是二进制的,无法储存中文,所以需要设置默认字符集,这是采取命令进行设置
还有通过配置mysql.cnf可以设置全局的数据库字符集,这个比较推荐
用法:在db容器中挂载宿主机里准备好的mysql.cnf
- "./mysql.cnf:/etc/mysql/conf.d/mysql.cnf"
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
init_connect='SET collation_connection = utf8mb4_unicode_ci'
init_connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
需要在settings.py里设置数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '数据库名字',
'USER': 'root',
'PASSWORD': '密码',
'HOST': 'db', # 这里填写容器名称
'PORT': '3306',
'OPTIONS': {'charset': 'utf8mb4'},
}
}
selebium-hub是负责chrome容器与python之间的交互,因为一些爬虫程序是需要selenium来做
这里注意:
selenium-hub的版本要与chrome一致
START_XVFB=false
以无头模式运行,默认是true
SE_NODE_SESSION_TIMEOUT
网格 URL 和会话超时,默认300秒
SE_SESSION_RETRY_INTERVAL=2
重试间隔为 2 秒
–scale chrome=num
docker-compose up -d --scale chrome=num //num是要启动节点的数量,chrome是docker-compose文件中浏览器结点的名称
使用方法
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# chrrome版本大于88
opt = Options()
opt.add_argument('--headless')
driver = webdriver.Remote(command_executor='http://selenium-hub:4444/wd/hub', options=opt)# 服务器设置
要加上http才能连接上,然后是容器名字,后面的是固定的,然后要设置以无头浏览器运行
./config/nginx:/etc/nginx/conf.d
挂载nginx设置,
upstream app {
ip_hash;
server app:8000; //监听app容器的8000端口
}
server {
listen 8000;
server_name localhost;
client_max_body_size 50m;
location /static/ {
autoindex on;
alias /code/static/;
}
location / {
proxy_pass http://app/;
}
}
之后在requirements.txt文件的最后两行增加mysqlclient库和gunicorn库。
mysqlclient==2.0.1
gunicorn==19.9.0
部分内容参考:Docker-compose部署Django