# 安装docker
yum install docker -y
# 启动|关闭|重启docker服务
systemctl start|stop|restart docker
# 开机启动docker
systemctl enable docker
# 查看docker当前状态
systemctl status docker
# 测试docker是否正确安装及功能完备
docker run hello-world
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://***.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 获取docker版本
docker version
# 详细信息,包括容器信息
docker info
# 测试docker是否正确安装及功能完备
docker run hello-world
群晖nas:需管理员权限
sudo -i
,获取root权限,密码是登录用户名密码
# 现实镜像列表
docker images
# 拉取nginx镜像:pull 镜像名:版本号,
# 省略版本号即为latest,镜像都自带系统
docker pull nginx:1.20
# 删除镜像
# docker rmi nginx:1.20
centos镜像存放的地址:/var/lib/docker/image/overlay2/imagedb/content/sha256
# 创建并启动容器:
# -d: 后台运行
# -i:容器开启交互接口,若容器内无循环逻辑,则立即exit
# --name: 容器别名
# -p: 映射端口,宿主端口:容器虚拟机端口,多映射写法-p x:x -p x:x
# 构建容器的最底层镜像:镜像:版本号,若本机没有,docker自动pull
# 网络:--net=host与主机共享IP和端口,none无网络,bridge默认虚拟网络
docker run -id --name nginx_test -p 8080:80 nginx:1.20
# docker容器运行必须有一个前台进程, 如果没有前台进程执行,容器
# 认为空闲,就会自行退出,-i(容器开启交互接口)
docker run -id --name python3 python:3.8
# 显示已启动的容器详情列表,-a可以显示包括关闭的容器
# 各列说明见下表
docker ps [-a]
# 容器重命名
docker rename 原容器名 新容器名
# 拷贝文件:从宿主到容器,container为容器名,也可为容器序号
# 将dir文件夹拷贝到root目录内,注意斜杠
docker cp ./dir container:/root/
# 从容器到宿主机
docker cp container:/root ./dir/
表头 | 数据 | 释义 |
---|---|---|
CONTAINER ID | aa67260f166d | 自动分配容器序号 |
IMAGE | nginx:1.20 | 镜像 |
COMMAND | “/docker-entrypoint.…” | 容器启动后立即执行的命令、脚本 |
CREATED | 4 minutes ago | 容器创建时间 |
STATUS | Up 4 minutes | 容器状态:created(已创建)restarting(重启中)running(运行中)removing(迁移中)paused(暂停)exited(停止)dead(死亡) |
PORTS | 0.0.0.0:8080->80/tcp | 容器端口映射,宿主端口=>容器端口/协议 |
NAMES | nginx_test | 容器别名 |
# 容器名:可以用别名,也可以用序号,位数能区分容器即可
# 重启容器:取序号前两位,位数能区分容器即可
docker restart aa
# 关闭容器:取容器别名
docker stop nginx_test
# 开启容器:取容器前一位
docker start a
# 进入容器内:
# exec:退出容器,不关闭容器
# -i(容器开启交互接口),-t(创建伪终端)
# aa6: 容器序号前三位
# /bin/bash:进入容器后启动的shell
docker exec -it aa6 bash
# 退出伪终端命令为:exit
# 删除容器,配合docker ps -a使用
# docker rm aa
容器内操作系统:基本为Ubuntu、centos,下载工具分别为apt、yum,简单判断看下面哪个命令能运行
网络工具:
- Ubuntu:
更新源缓存:apt update
安装网络工具:apt install net-tools
安装ping工具:apt install iputils-ping
安装ssh:apt install openssh-server
/etc/sshd_config取消注释并修改此行PermitRootLogin yes和PasswordAuthentication yes
范例:封装uwsgi和Django项目到一个镜像里
[uwsgi]
# 版本为2.0.20,以下为必要设置,其他采用默认
# 启动一个主程序管理其他进程
master=true
# 进程数:2倍cpu核心数,跟worker
processes = 2
# 每个进程中开启线程数
threads=2
# 通信接口:直接作为web服务器使用,注意IP
# 也可写为0:2048,表示对访问的IP无限制
http=0.0.0.0:2048
# 项目启动后的根目录
chdir=/home/www/backend
# uwsgi服务器进入Django项目的入口
# 绝对路径:/home/www/backend/main/wsgi.py
module = main.wsgi:application
# pid文件,通过其可以控制uwsgi服务器的停止和重启
pidfile=uwsgi.pid
# 日志存放位置,根目录下,用daemonize设置有问题
logto=uwsgi.log
# 服务器退出时自动删除socket和pid文件
vacuum=true
# 日志最大大小
log-maxsize=50000
# 每个进程最多请求数,达到立即回收重用此进程
max-requests=1000
# 前后端传输数据大小:单位kb,要是文件上传下载需要注意此处
buffer-size = 65536
FROM python:3.8
LABEL author="chuck<******@qq.com>"
WORKDIR /home/www/backend
ADD . /home/www/backend
RUN pip install -r requirements.txt \
-i http://pypi.douban.com/simple \
--trusted-host pypi.douban.com \
&&pip install uwsgi \
-i http://pypi.douban.com/simple \
--trusted-host pypi.douban.com
ENTRYPOINT /usr/local/bin/uwsgi --ini /home/www/backend/uwsgi.ini
Dockerfile中不可有注释
FROM:后接构建自定义镜像的模板镜像
LABEL:标签,key:value形式
WORKDIR:指定后续语句的工作目录,相当于cd命令,docker exec进入的也是此文件夹
ADD:拷贝宿主机文件到镜像,宿主机若为路径如:/home/www,则仅拷贝其中文件到
镜像文件夹内,优势是源文件是压缩文件,此命令会先解压再拷贝进镜像
RUN:构建镜像,在镜像内运行的命令,每个RUN在镜像中生成一层,效率与层数成反比,
用此种写法,仅生成一层,多个命令写法
ENTRYPOINT:使用此镜像,docker run命令生成容器,容器启动后第一个执行的语句
cd 父目录/project
# -t后面接的是 镜像名:版本号,别落了最后的点儿
# 点号:是指镜像构建时打包上传到Docker引擎中的文件的目录
docker build -t django:v1.0 .
# 查看镜像创建情况
docker images
# 创建自定义镜像的容器:请求在端口流转,宿主2000=>docker中uwsgi的2048端口=>
# 通过uwsgi配置文件传给main/wsgi.py,进而进入Django项目
docker run -id --name django_v1.0 -p 2000:2048 django:v1.0
# 可进入运行中的容器,退出的容器可以`docker log 容器序号`查看原因
docker exec -it django_v1.0 bash
# /usr/local/bin/docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.28.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 授予可执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 安装完成,查看版本
docker-compose version
# yml格式版本:3.8版本匹配docker engine版本19.03.0+
# 版本由docker version获取
version: '3.8'
# 服务:每一个对应一个容器
services:
# 服务名:随便起,也为容器IP地址别名,即nginx对应172.3.2.1这样
nginx:
# docker拉取镜像创建容器
image: nginx:1.20
# 启动的容器名:对应docker run --name 这项
container_name: nginx_main
# 若关闭,自动重启,前提是docker守护进程在运行,即docker开着
restart: always
# 端口暴露:对应docker run -p 这项
ports:
- 80:80
- 443:443
# 给另一个服务的容器的IP设置别名,此处django对应
# 容器be_localip的IP,用一个yml文件生成的容器均在同
# 一个局域网中,单一网络中直接用服务名即可,此项较少用
links:
- "be_localip:django"
# 设置容器启动依赖关系:此项仅限制各服务的启动次序,
# 不代表be_localip启动完成再启动nginx,若要完成后再启动
# 官网有wait-for的command的相关设置
depends_on:
- be_localip
# 见db处volumes注释
volumes:
# vue打包项目,即index.html所在目录
# win10中测试相对路径可行,不用绝对路径写法
- ./0_frontend/html:/usr/share/nginx/html
# ngingx配置目录、文件(虚拟机及通用配置)
- ./0_frontend/conf.d:/etc/nginx/conf.d
- ./0_frontend/nginx.conf:/etc/nginx/nginx.conf
be_localip:
# 此容器镜像通过./1_backend/localIPBE/Dockerfile创建
# win10中测试相对路径可行,不用绝对路径写法
build: ./1_backend/localIPBE
container_name: BE_localIP
restart: always
# 此处只写一个,即指定宿主机任意端口绑定此容器的2048端口,
# 实质是仅将此端口暴露给内部容器使用,不给宿主机用
ports:
- 2048
depends_on:
- db
# 多后端写法示例,nginx配置文件做重定向此后端
# BE_doubi:
# build: ./1_backend/doubi.com
# container_name: BE_doubi
# restart: always
# ports:
# - 2049
db:
image: postgres:12.10
container_name: postgres_main
restart: always
ports:
- 5432:5432
# 设定环境变量:数据库名、用户名、密码、时区,
# 在Django的setting进行对应设置
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- TZ=Asia/Shanghai
# 挂载卷:
# 1、功能:将postgresql的数据卷挂载到宿主机对应目录下
# 2、docker命令:对应`docker run -v 宿主机目录:容器内目录`
# 3、特性:默认宿主机目录(不管是否为空)覆盖(而非删除)容器目录;数据库镜像此
# 设置特殊,经测试宿主机为空目录,会被容器目录反向拷贝填满,但若宿主机目录非空,则
# 宿主机目录覆盖容器目录
# 4、数据持久性:两目录数据同步,停止甚至销毁容器,宿主目录不变,可多容器绑定
# 同一宿主目录
volumes:
- ./2_database/postgres:/var/lib/postgresql/data
nginx配置文件及性能优化详见:传送门,以下是精简版nginx配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# 重定向服务器错误页到静态页面50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
listen 80;
server_name 192.168.3.120;
location /api/ {
# 重写路由:
# rewrite 匹配路由 替换路由 flag
# $1为括号内正则,break替换后不再做location等匹配
rewrite /api/(.*) /$1 break;
# 包含uwsgi_params模块
include uwsgi_params;
# django:为前端服务器的IP,yml中指定
uwsgi_pass django:2048;
}
location / {
root /usr/share/nginx/html/localIP/;
# 解决刷新页面404问题,可以不加看效果
try_files $uri $uri/ /index.html;
index index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
# 监听80和443端口,后面rewrite语句会强制将80转成443
listen 80;
listen 443 ssl http2;
server_name doubi.com;
# 此处偷懒,都指向相同的vue前端,后续location中root在此后拼接
root /usr/share/nginx/html/localIP/;
# 将404导给前端做路由跳转
# error_page 404 https://doubi.com/404.html;;
# 强制http转https:rewrite语句
# permanent:浏览器地址栏显示重定向后的url
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
# ssl密钥和证书:在注册域名处提取,并放到如下目录处
# centos中cert转pem命令如下:
# openssl x509 -in doubi.com.crt -out doubi.com.pem -outform PEM
ssl_certificate /etc/nginx/conf.d/certificate/doubi.com.pem;
ssl_certificate_key /etc/nginx/conf.d/certificate/doubi.com.key;
# ssl加密协议、算法
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
# 在使用SSLv3和TLS协议时,服务器加密算法将优于客户端加密算法
ssl_prefer_server_ciphers on;
# 设置存储session参数的缓存的类型和大小:缓存在所有工作进程之间共享
ssl_session_cache shared:SSL:10m;
# 设置存储session的缓存过期时间
ssl_session_timeout 10m;
# 添加响应头:告诉浏览器只能通过HTTPS访问当前资源, 禁止HTTP方式
add_header Strict-Transport-Security "max-age=31536000";
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
#禁止访问的文件或目录
# location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
# {
# return 404;
# }
# 设置浏览器上缓存图片资源过期时间
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 7d;
error_log /dev/null;
access_log /dev/null;
}
# 设置浏览器上js、css资源过期时间
location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
location / {
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
# main为格式:见nginx.conf
access_log /var/log/nginx/doubi.com.log main;
# info为错误等级
error_log /var/log/nginx/doubi.com.error.log info;
}
本机测试doubi.com:需要在本机host文件(C:\Windows\System32\drivers\etc\hosts)增加一行
127.0.0.1 doubi.com
获取ssl密钥文件:腾讯管理的域名、阿里管理的域名
django项目settings.py修改
"""
...
# 开启生产环境
DEBUG = False
...
# 开启访问白名单
ALLOWED_HOSTS = ['*']
...
# 此处设置postgresql参数
DATABASES = {
'default': {
# 此模块要pip install psycopg2-binary
'ENGINE': 'django.db.backends.postgresql_psycopg2',
# 以下与docker-compose.yml中配置相对应
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
# 在yml文件中,db为数据库所在虚拟机的IP
'HOST': 'db',
'PORT': '5432',
}
}
...
# 此处是关闭跨域访问限制
CORS_ALLOW_ALL_ORIGINS = True
...
Dockerfile
FROM python:3.8
LABEL author="chuck<******@qq.com>"
WORKDIR /home/www/backend
ADD . /home/www/backend
RUN pip install -r requirements.txt \
-i http://pypi.douban.com/simple \
--trusted-host pypi.douban.com \
&&pip install uwsgi \
-i http://pypi.douban.com/simple \
--trusted-host pypi.douban.com
ENTRYPOINT /usr/local/bin/uwsgi --ini /home/www/backend/uwsgi.ini
requirements.txt
# 注意补充这个连接postgresql数据库的模块
pip install psycopg2-binary
pip freeze > requirements.txt
uwsgi.ini
[uwsgi]
master=true
processes = 2
threads=2
# nginx由此处进入uWSGI服务器
# 对应nginx中uwsgi_pass
socket=0.0.0.0:2048
chdir=/home/www/backend
# uwsgi服务器从此处进入Django项目
module = main.wsgi:application
pidfile=uwsgi.pid
logto=uwsgi.log
vacuum=true
log-maxsize=50000
max-requests=1000
buffer-size = 65536
# 以下命令均需要在yml文件所在目录中运行
# 侦测yml文件中build项,镜像有更新需要主动运行此命令
docker-compose build
# 首次运行会调用docker build和docker run针对每个容器
# -d:可选项,为后台运行,建议先不带看运行详情,没问题再-d
docker-compose up [-d]
# 停止并删除yml管理的容器,包含挂载的卷volume,不删镜像
docker-compose down
# 启动、停止、重启服务容器集群
docker-compose start|stop|restart
# 容器集群启动起来后需要做Django项目数据库迁移
docker exec -it BE_localIP bash
> python manage.py makemigrations
> python manage.py migrate
> python manage.py createsuperuser
# 查看挂载卷信息
docker volume ls
# 删除挂载卷:卷标上条命令
docker volume rm 卷序号
# 打印容器输出日志:序号获取 docker ps -a
docker logs 容器序号
# 查看容器详细信息
docker inspect 容器序号
docker run -id --network host nginx:1.20
在win10和mac上失效bridge模式:docker0相当于一个网桥,每个veth为一个路由器,docker0控制NAT端口映射和iptables规则,此模式下的相同网络名称的容器相当于在一个局域网中,由veth控制IP段,经过docker0,IP即被docker0和宿主机的iptables规则调整
host模式:容器直接使用宿主机的IP和端口,注意控制端口冲突,因为直接接触外网,性能更好
# 此命令会获取centos7完整权限,否则很多系统权限无法获得
docker run -itd --name centos7 --privileged --network host centos:7 init
# 进入docker容器
docker exec -it centos7 bash
# 安装systemctl
yum install initscripts -y
# 安装网络工具:如ping、ifconfig
yum install net-tools -y
# 安装ssh
yum install openssh-server -y
# 安装epel
yum install epel-release
# 未注释的均为原样
version: '3.8'
services:
nginx:
image: nginx:1.20
container_name: nginx_main
restart: always
# 此处修改为host模式:与主机共用端口和IP
# 此网络模式不与ports、links共存
network_mode: host
depends_on:
- be_localip
volumes:
- ./0_frontend/html:/usr/share/nginx/html
- ./0_frontend/conf.d:/etc/nginx/conf.d
- ./0_frontend/share:/usr/share/nginx/share
- ./0_frontend/nginx.conf:/etc/nginx/nginx.conf
be_localip:
build: ./1_backend/localIPBE
container_name: BE_localIP
restart: always
# 此处用bridge模式将端口暴露给主机
# 留给Nginx与后端uwsgi通信用:localhost:2048这样
ports:
- 2048:2048
depends_on:
- db
...
location /api/ {
rewrite /api/(.*) /$1 break;
# 客户端IP:若经过多个反向代理,此为最后一个代理IP
# 后端获取此值:request.META["X-Real-IP"]
uwsgi_param X-Real-IP $remote_addr;
# 逗号分隔值:如"1.1.1.1,2.2.2.2"这样,首元素为客户端真实IP,
# 后续为经过的反向代理服务器IP
# 后端获取此值:request.META["X-Forwarded-For"]
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
include uwsgi_params;
# 此处不能用be_localip,因为Nginx跟主机同级,be_localip在容器里
uwsgi_pass localhost:2048;
}
...
跳转至:宝塔版nginx+uwsgi+django+vue