Docker完整知识点整理
目录
- Docker部署安装
- Docker加速器&镜像常用操作
- 容器基础操作
- 容器和主机之间拷贝文件 + docker commit提交镜像
- Dockerfile镜像构建(多阶段构建distroless最小镜像)
- Docker私有仓库(registry、https证书、账号认证、Harbor企业仓库)
- Docker网络(默认网络、自定义bridge、网络栈共享、macvlan跨主机通信)
- Docker数据卷(bind mount、managed volume、数据卷容器、备份迁移)
- Docker安全加固(资源限制、lxcfs、cap权限、privileged)
- Docker Compose使用(yml语法、实战haproxy负载均衡)
1、Docker部署安装
原理
dnf安装docker‑ce,开启内核网络转发、br_netfilter网桥模块,保证容器网络NAT正常工作。
操作步骤
#1.配置阿里云docker‑ce源
cat > /etc/yum.repos.d/docker.repo << EOF
[docker]
name = docker
baseurl = [https://mirrors.aliyun.com/docker](https://mirrors.aliyun.com/docker)‑ce/linux/rhel/9.8/x86_64/stable/
gpgcheck = 0
EOF
#2.更新缓存,卸载冲突podman
dnf makecache
dnf remove podman -y
#3.安装docker‑ce
dnf install docker‑ce -y
#4.修改docker service配置开启iptables
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
#5.加载网桥内核模块
echo br_netfilter > /etc/modules‑load.d/docker_mod.conf
modprobe -a br_netfilter
#6.内核sysctl网络转发参数
cat > /etc/sysctl.d/docker.conf <<EOF
net.bridge.bridge‑nf‑call‑iptables = 1
net.bridge.bridge‑nf‑call‑ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
#7.启动开机自启docker
systemctl enable --now docker
截图

2、Docker加速器 & 镜像常用命令
原理
docker默认访问国外hub,配置registry‑mirrors国内镜像加速器加速拉取镜像。
2.1配置加速器
#编辑daemon.json配置加速器
cat > /etc/docker/daemon.json <<EOF
{
"registry‑mirrors": ["[https://docker.1ms.run](https://docker.1ms.run)"]
}
EOF
systemctl restart docker
#查看加速器是否生效
docker info
截图

2.2镜像常用操作
| 命令 | 解释 |
|---|---|
docker images |
列出本地镜像 |
docker search nginx |
搜索hub镜像 |
docker pull nginx |
下载镜像 |
docker history busybox:latest |
查看镜像分层历史 |
docker save -o 2048.tar 镜像名:tag |
导出镜像为tar包 |
docker load -i 2048.tar |
导入tar镜像包 |
docker rmi 镜像名:tag |
删除镜像 |
截图

3、容器基础操作
3.1后台运行容器
#‑d后台,‑‑name自定义容器名
docker run -d --name web nginx:1.26
#查看运行的容器
docker ps
#查看全部(包含停止)容器
docker ps -a
截图

3.2交互模式容器
# ‑it 交互式终端
docker run -it --name box busybox:latest
#快捷键 Ctrl+p+q 退出但是容器不停止
#重新attach进入
docker attach box
#启动停止的容器
docker start box
#停止容器
docker stop box
#强制杀死容器
docker kill box
#删除容器
docker rm -f box
docker run -it直接exit会直接停止容器;Ctrl+p+q`剥离终端,容器后台继续运行。
截图

3.3 exec 在运行容器执行命令
#非交互执行命令
docker exec web touch /root/haha
#交互式进入容器shell
docker exec -it web /bin/bash
3.4 docker commit 将容器修改保存镜像
原理:把运行容器当前读写层打包生成新镜像,不推荐生产,适合测试。
#运行nginx,修改页面
docker run -d --name webserver -p 80:80 nginx:latest
docker exec -it webserver /bin/bash
echo "hello timinglee" > /usr/share/nginx/html/index.html
exit
#提交生成新镜像
docker commit -m "modify index.html" webserver nginx_index:latest
#测试新镜像
docker rm -f webserver
docker run -d -p 80:80 --name webserver nginx_index:latest
curl 127.0.0.1
4、容器和宿主机之间拷贝文件
操作步骤
#宿主机文件复制到容器内:docker cp 源 容器名:容器内路径
docker cp index.html webserver:/usr/share/nginx/html
#容器文件拷贝到宿主机:docker cp 容器名:容器路径 宿主机路径
docker cp webserver:/usr/share/nginx/html/index.html /mnt
截图

5、Dockerfile构建镜像
Dockerfile指令说明
| 指令 | 作用 |
|---|---|
FROM xxx:tag |
基础镜像,必须第一条 |
COPY 本地 容器路径 |
复制文件,不解压压缩包 |
ADD 本地 容器路径 |
复制,自动解压tar压缩包 |
LABEL key=value |
镜像元数据标签 |
ENV NAME=xxx |
设置环境变量 |
RUN shell命令 |
构建镜像时执行命令,生成镜像层 |
EXPOSE 8080 |
声明暴露端口,只是文档,不实际映射端口 |
VOLUME /mnt |
声明数据卷,自动生成匿名卷 |
WORKDIR /mnt |
设置容器工作目录 |
CMD ["sh","‑c","xxx"] |
容器启动默认命令,可以被run后面参数覆盖 |
ENTRYPOINT ["xxx"] |
容器启动入口,run追加参数作为参数传给程序 |
CMD和ENTRYPOINT区别: CMD:
docker run 镜像 新命令会完全替换CMD; ENTRYPOINT:run后面内容作为参数追加给ENTRYPOINT程序。
5.1简单Dockerfile示例
mkdir docker && cd docker
echo "timinglee" > timinglee
vim Dockerfile
Dockerfile内容
FROM busybox:latest
LABEL Creater=lee
COPY timinglee /root
ENV NAME=timinglee
EXPOSE 8080
WORKDIR /mnt
CMD ["/bin/sh","‑c","echo $NAME"]
构建镜像
# ‑t 镜像名:tag .代表构建上下文当前目录
docker build -t timinglee:v1 .
#运行
docker run --rm timinglee:v1
5.2实战:debian源码编译nginx,多阶段distroless最小镜像
原理:第一阶段build镜像做编译环境,第二阶段distroless无操作系统基础镜像,只复制编译产物和依赖库,镜像体积大幅缩小。
阶段1:编译nginx镜像Dockerfile
FROM debian:latest
ADD nginx‑1.30.4.tar.gz /mnt
WORKDIR /mnt/nginx‑1.30.4
RUN apt update && apt install -y ca‑certificates build‑essential libpcre2‑dev zlib1g zlib1g‑dev libssl‑dev libgd‑dev libxml2‑dev libxslt‑dev && ./configure --with‑http_ssl_module --with‑http_stub_status_module && make && make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
构建:docker build -t nginx‑debian13:latest .
阶段2:多阶段构建distroless最小镜像
#构建阶段
FROM nginx‑debian13:latest AS build
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/local/nginx /opt && \
cp -a --parents /usr/lib/x86_64‑linux‑gnu/libcrypt* /opt && \
cp -a --parents /usr/lib/x86_64‑linux‑gnu/libpcre2‑8* /opt && \
cp -a --parents /usr/lib/x86_64‑linux‑gnu/libssl* /opt && \
cp -a --parents /usr/lib/x86_64‑linux‑gnu/libcrypto* /opt && \
cp -a --parents /usr/lib/x86_64‑linux‑gnu/libz* /opt && \
cp -a --parents /usr/lib/x86_64‑linux‑gnu/libc* /opt && \
cp -a --parents /usr/lib/x86_64‑linux‑gnu/libzstd* /opt
#最终运行镜像,无shell工具,体积小安全
FROM gcr.io/distroless/base‑debian13:latest
COPY --from=build /opt /
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
ENTRYPOINT ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
构建:docker build -t nginx‑lee:v1 .
部分截图

6、Docker私有仓库
6.1简单http registry仓库(无加密无认证)
#导入registry镜像
docker load -i registry‑202608.tar
#启动仓库容器,5000端口
docker run -d --name registry --restart=always -p 5000:5000 registry:latest
#给镜像打标签 仓库地址:端口/镜像名:tag
docker tag nginx‑lee:v1 172.25.254.10:5000/nginx‑lee:v1
问题:docker默认强制https,http仓库推送报错。 修改daemon.json添加不安全仓库:
{
"insecure‑registries":["[http://172.25.254.10:5000](http://172.25.254.10:5000)"]
}
systemctl restart docker
推送镜像:
docker push 172.25.254.10:5000/nginx‑lee:v1
#api查看仓库镜像列表
curl [http://172.25.254.10:5000/v2/_catalog](http://172.25.254.10:5000/v2/_catalog)
#其他节点下载镜像,其他节点同样配置insecure‑registries
docker pull 172.25.254.10:5000/nginx‑lee:v1
截图

6.2 registry开启HTTPS证书加密
1.openssl生成自签名证书key crt
mkdir certs
openssl req -newkey rsa:4096 -nodes \
-keyout certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \
-x509 -days 365 -out certs/timinglee.org.crt
2.带证书启动registry容器,监听443
docker run -d --name registry \
--restart=always -p 443:443 \
-v /root/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key \
registry
3.客户端信任证书:docker证书目录/etc/docker/certs.d/reg.timinglee.org/ca.crt复制crt文件,重启docker。 4.配置/etc/hosts解析reg.timinglee.org指向仓库主机IP。 5.tag、push、pull使用域名reg.timinglee.org/busybox:latest。
截图

6.3 registry开启htpasswd账号密码认证
#生成htpasswd密码文件
mkdir auth
htpasswd -cB auth/htpasswd admin
#启动仓库挂载auth目录,开启htpasswd认证
docker run -d --name registry \
--restart=always -p 443:443 \
-v /root/certs:/certs \
-v /root/auth:/auth \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry
操作:
#登录仓库
docker login reg.timinglee.org -u admin
#登出
docker logout reg.timinglee.org
不登录无法push/pull镜像。
截图

6.4 Harbor企业镜像仓库
1.解压harbor离线包
tar zxf harbor‑offline‑installer‑v2.14.0.tgz -C /opt/
cd /opt/harbor
cp harbor.yml.tmpl harbor.yml
2.修改harbor.yml
hostname: reg.timinglee.org
certificate: /data/certs/timinglee.org.crt
private_key: /data/certs/timinglee.org.key
harbor_admin_password: lee
3.执行安装脚本
./install.sh
4.访问浏览器[https://reg.timinglee.org](https://reg.timinglee.org),admin/lee登录,新建项目,打tag推送镜像。 5.配置systemd管理harbor服务(使用docker compose管理启停)。
截图

7 Docker网络 docker网络驱动:bridge桥接、host主机网络、none无网络、macvlan跨主机二层网络。
7.1查看网络
docker network ls
docker network inspect 网络名
默认3个网络:bridge(docker0)、host、none。
7.2自定义bridge网络
重点区别:默认bridge(docker0)没有DNS容器名解析;自定义bridge支持容器名字互相ping通。
#创建默认自定义桥接
docker network create mynet1
#指定子网网关创建
docker network create mynet2 --subnet 192.168.0.0/16 --gateway 192.168.0.100
测试dns解析:
#两个容器加入同一个自定义网络mynet1
docker run -d --name c1 --network mynet1 nginx
docker run -it --name c2 --network mynet1 busybox
#在c2中 ping c1,直接用容器名字通信
ping c1
截图

7.3容器连接多个网络 docker network connect 网络名 容器名,给已经运行的容器追加网卡接入另一个网络。
docker network connect mynet2 c2
#容器内ifconfig看到eth0、eth1两块网卡
截图

7.4 共享网络栈 network_mode:container:容器名
多个容器共用同一个网络命名空间,IP、端口完全一样,可以127.0.0.1互相访问。
docker run -d --name web --network mynet1 nginx
#新容器复用web的网络栈
docker run -it --rm --network=container:web busyboxplus
#容器内 curl 127.0.0.1 访问nginx
curl 127.0.0.1
实战:phpmyadmin和mysql共用网络栈,mysql不需要暴露端口给外部。
docker run -d --name phpmyadmin --network=mynet1 -e PMA_ARBITRARY=1 -p 80:80 phpmyadmin
docker run -d --name mysql --network=container:phpmyadmin -e MYSQL_ROOT_PASSWORD='lee' mysql:8.0
截图

7.5 macvlan跨主机容器通信
macvlan:容器分配独立物理网段IP,直接在二层交换机通信,不同宿主机上容器直接互通。
每台宿主机操作:
#物理网卡eth1开启混杂模式
ip link set eth1 promisc on
ip link set up eth1
#创建macvlan网络,父网卡eth1,网段1.1.1.0/24
docker network create -d macvlan --subnet 1.1.1.0/24 --gateway 1.1.1.1 -o parent=eth1 macvlan1
node1运行容器指定ip:
docker run -it --name test1 --rm --network=macvlan1 --ip 1.1.1.100 busybox
node2运行容器:
docker run -it --name test2 --rm --network=macvlan1 --ip 1.1.1.200 busybox
互相ping对方IP,跨主机容器直接通信。
截图效果

8 Docker数据卷 三种存储:bind‑mount绑定挂载、docker managed volume管理卷、volumes‑from数据卷容器。
8.1 bind‑mount 绑定挂载 -v 宿主机路径:容器路径:[ro/rw]
ro只读;rw读写;宿主机目录不存在docker自动创建目录。
# /mnt/data宿主机目录挂载容器/data;/etc/passwd只读挂载
docker run -it --rm -v /mnt/data:/data -v /etc/passwd:/passwd:ro busybox
截图

8.2 docker managed volume docker管理卷
#创建管理卷
docker volume create timinglee
docker volume ls
#挂载管理卷到容器
docker run -it --rm -v timinglee:/data busybox
#卷实际宿主机路径:/var/lib/docker/volumes/timinglee/_data
#删除卷
docker volume rm timinglee
8.3 volumes‑from 数据卷容器
复用别的容器已经定义的所有volume挂载,不复制数据,直接共享挂载。
#数据容器data,定义挂载
docker run -it --rm --name data -v /data:/data busybox
#lee容器复用data全部挂载
docker run -it --rm --name lee --volumes‑from data busybox
8.4 卷数据备份和恢复
备份
#webserver容器挂载/data
#启动临时busybox,复用webserver卷,把当前目录挂载/backup,tar打包
docker run -it --rm --volumes‑from webserver -v $(pwd):/backup busybox
tar zcf /backup/html.tar.gz /usr/share/nginx/html
exit
#当前目录得到备份包html.tar.gz
恢复
#把备份包解压回容器卷
docker run -it --rm --volumes‑from webserver -v $(pwd):/backup busybox
tar zxf /backup/html.tar.gz -C /
截图

9 Docker安全加固
9.1资源限制
CPU限制
#‑‑cpu‑period 100000周期;‑‑cpu‑quota 20000代表最多20%cpu
docker run -it --rm --cpu-period 100000 --cpu-quota 20000 ubuntu
#‑‑cpu‑shares 权重,多容器争抢CPU时权重分配,默认1024
docker run -it --rm --cpu-shares 100 ubuntu
内存限制
#最大内存200M,swap也200M
docker run -d --name test --memory 200M --memory-swap 200M nginx
磁盘IO限速
#写bps限制30M/s
docker run -it --rm --device‑write‑bps /dev/nvme0n1:30M ubuntu
9.2 lxcfs插件,容器内看到限制的资源而不是宿主机全部硬件
不装lxcfs容器free -m看到宿主机全部内存,安装lxcfs挂载proc虚拟文件后,容器内看到限制的内存。
dnf install lxcfs -y
lxcfs /var/lib/lxcfs &
#启动容器挂载lxcfs的proc文件
docker run -it -m 256m \
-v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
-v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
-v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
ubuntu
#容器free -m显示256M
截图

9.3容器权限控制
1.‑‑privileged完整宿主机内核权限(高危,尽量不要使用)
docker run -it --rm --privileged busybox
2.最小权限:‑‑cap‑add CAP_NET_ADMIN只增加指定能力,而不是全部特权。
docker run -it --rm --cap-add CAP_NET_ADMIN busybox
#可以在容器配置网卡ip,不能操作磁盘块设备fdisk
10 Docker Compose
docker compose:多容器编排工具,yml定义一组服务,统一启停管理。
常用命令
docker compose up -d #后台启动服务
docker compose ps #查看服务状态
docker compose logs web #查看日志
docker compose stop/start #停止/启动
docker compose restart #重启
docker compose down #停止并且删除容器,默认不删卷
docker compose build #构建Dockerfile镜像
docker compose exec 服务名 sh #进入容器
docker compose -f xxx.yml up -d #指定yml文件
yml文件关键字段
services:
web:
image: nginx:1.23
container_name: web1
ports:
- "80:80"
expose:
- 8080
environment:
MYSQL_ROOT_PASSWORD: lee
build: #构建镜像参数
context: ./
dockerfile: Dockerfile
volumes:
- webdata:/usr/share/nginx/html
networks:
- mynet1
depends_on: #启动依赖,先启动依赖服务
- mysql
network_mode: service:xxx #共享网络栈
networks:
mynet1:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
gateway: 172.28.0.254
default:
external: true #使用宿主机已经存在的网络
volumes:
webdata:
name: webdata1
实战:haproxy负载均衡两个nginx web docker‑compose.yml
services:
web1:
image: nginx:1.23
container_name: web1
networks:
- mynet1
volumes:
- "webdata1:/usr/share/nginx/html"
web2:
image: nginx:1.23
container_name: web2
networks:
- mynet1
volumes:
- "webdata2:/usr/share/nginx/html"
haproxy:
image: haproxy:2.3
container_name: haproxy
networks:
- mynet1
volumes:
- "/conf/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg"
ports:
- "80:80"
networks:
mynet1:
driver: bridge
volumes:
webdata1:
name: webdata1
webdata2:
name: webdata2
准备haproxy.cfg配置:
listen webserver_80
bind *:80
mode http
server webserver1 web1:80 check inter 3s fall 3 rise 5
server webserver2 web2:80 check inter 3s fall 3 rise 5
docker compose up -d
#修改两个web页面
echo web1 > /var/lib/docker/volumes/webdata1/_data/index.html
echo web2 > /var/lib/docker/volumes/webdata2/_data/index.html
#循环curl测试负载均衡
for i in {1..10};do curl 127.0.0.1;done
截图
sr/share/nginx/html"
haproxy:
image: haproxy:2.3
container_name: haproxy
networks:
- mynet1
volumes:
- "/conf/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg"
ports:
- "80:80"
networks:
mynet1:
driver: bridge
volumes:
webdata1:
name: webdata1
webdata2:
name: webdata2
准备haproxy.cfg配置:
listen webserver_80
bind *:80
mode http
server webserver1 web1:80 check inter 3s fall 3 rise 5
server webserver2 web2:80 check inter 3s fall 3 rise 5
docker compose up -d
#修改两个web页面
echo web1 > /var/lib/docker/volumes/webdata1/_data/index.html
echo web2 > /var/lib/docker/volumes/webdata2/_data/index.html
#循环curl测试负载均衡
for i in {1...10};do curl 127.0.0.1;done
### 截图
