“docker”
Docker的那些奇奇怪怪的知识
Docker-in-Docker问题
在docker容器中启动docker时,要有足够权限
1
2
3
4
5
6
#普通容器报错
failed to mount overlay: operation not permitted #overlay2 挂载失败
exec: "fuse-overlayfs": executable file not found #fuse-overlayfs 找不到
failed to create NAT chain DOCKER:
iptables: can't initialize iptables table `nat': Permission denied #iptables NAT 表创建失败
方案一:用宿主机 Docker + containerd
如果你只是想构建镜像、运行容器,可以在容器中安装 docker-cli,使用宿主机 docker socket
1
docker run -v /var/run/docker.sock:/var/run/docker.sock -ti centos bash
容器只是调用宿主机 Docker,不需要 docker daemon
方案二:要加足够权限
1
2
3
4
5
docker run -d \
--privileged \
--name mydocker \
-v /var/lib/docker \
docker:dind
主要作用参数:--privileged,表示开启了特权模式
什么是特权模式?
特权模式会让容器拥有所有 Linux Capabilities(内核能力)、直接访问宿主机的设备(/dev/*)、可以修改内核参数、管理 cgroups 等。
哪些命令在
--privileged容器里会直接影响宿主机?
iptables
1 2 iptables -F iptables -t nat -A ...挂载(mount)某些文件系统
1 2 mount -t overlay ... mount /dev/sda /mnt修改宿主机 sysctl 参数
1 sysctl -w net.ipv4.ip_forward=1直接访问宿主机设备(/dev)
1 2 cat /dev/sda dd if=/dev/zero of=/dev/sda加载内核模块(modprobe)
1 modprobe br_netfilter
方案三:在 Kubernetes 里运行, 需要特权 Pod
1
2
securityContext:
privileged: true
官方最佳实践(最小权限)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker run -d \
--name dind \
--privileged=false \
--security-opt seccomp=unconfined \ #Docker 的默认 seccomp 禁掉了 clone3, mount, setns 等关键 syscalls
--security-opt apparmor=unconfined \ #dockerd 无法正常启动 overlay2,更不能创建容器。
--cap-add SYS_ADMIN \ #挂载 overlay2 文件系统(核心,Docker 必须)
--cap-add NET_ADMIN \ #配置网桥、veth、iptables
--cap-add NET_RAW \ #ping、ARP、网络底层
--cap-add MKNOD \ #创建设备文件
--cap-add SYS_MODULE \ #某些情况下加载内核模块(多数系统允许)
--cap-add SYS_PTRACE \ #dockerd 某些监控功能需要
--tmpfs /run \
--tmpfs /var/run \
-v dind-storage:/var/lib/docker \
docker:dind
Docker 创建/挂载存储卷
Docker 容器本质是“无状态”的,一旦容器删除,容器内数据就会消失。为了实现数据持久化,就必须使用 Volume(卷) 或 绑定挂载(Bind Mount)。
创建Volume:Docker 官方推荐的持久化方式
1
docker volume create mydata #创建卷
1
docker volume ls #查看卷
1
2
3
4
5
6
docker volume inspect mydata #查看卷的详细信息
#类似输出
{
"Mountpoint": "/var/lib/docker/volumes/mydata/_data"
}
容器删除后(docker rm -f),数据仍在 mydata 里。
Bind Mount:把宿主机目录挂进去容器
适合 开发环境、需要直接操作宿主机文件 的场景
1
2
3
4
docker run -d \
-v /opt/app/data:/data \
--name app \
busybox
/opt/app/data是宿主机目录/data是容器内目录
适用于
- 修改宿主机配置文件并让容器实时使用
- 宿主机与容器共享日志
- 持久化数据库数据到宿主机指定目录(生产环境也常用)
Docker资源限制
(在启动容器时,可以对以下资源进行限制)
限制内存
1
2
3
4
docker run -d \
--memory=512m \ #容器可用的最大内存
--memory-swap=512m \ #内存 + swap 总量
nginx
限制 CPU 使用
1
2
3
docker run -d \
--cpus=1.5 \ #最多使用 1.5 个 CPU 核心
nginx
绑定指定 CPU 核心
1
2
3
docker run -d \
--cpuset-cpus="0,1" \ #只能用 CPU 0 和 1
nginx
限制进程数
1
2
3
docker run -d \
--pids-limit=200 \
nginx
限制磁盘 IO
1
2
3
4
docker run -d \
--device-read-bps /dev/sda:10mb \
--device-write-bps /dev/sda:5mb \
nginx
对于已经启动的容器
凡是走 cgroup 的,大多能在线改;
凡是涉及 namespace / 启动参数的,必须重建容器
1
2
3
4
5
docker update \
--cpus 2 \
--memory 1g \
--memory-swap 2g \
容器名或ID
除此之外,端口映射,磁盘映射,网络模式不可进行在线修改