reference
- Docker —— 从入门到实践 非常不错的一本书,与时俱进
- 你确定你会写 Dockerfile 吗
- Docker stop或者Docker kill为何不能停止容器
- P2P镜像分发Dragonfly使用
- Docker 数据持久化的三种方案
- Docker — 从入门到实践
- docker-proxy 存在合理性分析
- Docker 的原理
- Docker 存储驱动与磁盘文件系统 内含格式化磁盘,挂载磁盘
- 深入理解 cgroup 中的 cpuset
- 一次有趣的 Docker 容器网络排查
安装 docker
分享一篇CentOS 7 下 yum 方式安装 Docker 环境1
2
3
4
5
6
7sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce
sudo systemctl start docker
一个“容器”,实际上是一个由 Linux Namespace、Linux Cgroups 和 rootfs 三种技术构建出来的进程的隔离环境。
这三种技术介绍?
Namespace 的作用是“隔离”,它让应用进程只能看到该 Namespace 内的“世界”;而 Cgroups 的作用是“限制”
rootfs 只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核。在 Linux 操作系统中,这两部分是分开存放的,操作系统只有在开机启动时才会加载指定版本的内核镜像。正是由于 rootfs 的存在,容器才有了一个被反复宣传至今的重要特性:一致性。
docker commit,实际上就是在容器运行起来后,把最上层的“可读写层”,加上原先容器镜像的只读层,打包组成了一个新的镜像。当然,下面这些只读层在宿主机上是共享的,不会占用额外的空间。
docker volume
镜像的各个层,保存在 /var/lib/docker/aufs/diff 目录下,在容器进程启动后,它们会被联合挂载在 /var/lib/docker/aufs/mnt/ 目录中,这样容器所需的 rootfs 就准备好了。
volume /test 挂载出来之后,文件会出现在了宿主机上对应的临时目录里,但是如果你在宿主机上查看该容器的可读写层,虽然可以看到这个 /test 目录,但其内容是空的。
而由于使用了联合文件系统,你在容器里对镜像 rootfs 所做的任何修改,都会被操作系统先复制到这个可读写层,然后再修改。这就是所谓的:Copy-on-Write。
有些时候,会由于配置文件的出错导致容器运行失败,这个时候不能进入容器修改文件,只能去 /var/lib/docker/overlay2/ID/diff 下面,找到对应的配置文件进行修改。
docker 常用命令
1 | # 启动 docker 服务 |
docker logs
删除 logs 设置 logs Daemon configuration file
docker iptables
docker 默认会修改 iptables,但有时候会造成 iptables ip 限制失效的问题。如果对 iptables 比较了解的同学,可以 Prevent Docker from manipulating iptables
1 | # vim /etc/docker/daemon.json |
还有一种办法就是添加 DOCKER-USER If you need to add rules which load before Docker’s rules, add them to the DOCKER-USER chain. These rules are loaded before any rules Docker creates automatically.1
2
3
4
5
6
7
8
9
10
11
12
13*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A DOCKER-USER -s x.x.x.x -p tcp --dport 80 -j RETURN
-A DOCKER-USER -p tcp --dport 80 -j DROP
-A DOCKER-USER -p udp --dport 80 -j DROP
-A DOCKER-USER -j RETURN
COMMIT
Dockerfile
首先,安利一下 Dockerfile 优化指南
1 | FROM python:3.7 |
tag
docker 镜像有许多的版本,不同版本间差异需要注意。举个例子,我遇到因为版本不同,ip route get 结尾多了一个 uid 01
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#执行这个命令,在不同 tag 版本的 Python 镜像里,结果会不一样。
ip -4 route get 8.8.8.8
# 结果多了一个 uid 会导致提取 IP 时出错。
8.8.8.8 via 192.168.0.1 dev eth0 src 192.168.0.105 uid 0
8.8.8.8 via 192.168.0.1 dev eth0 src 192.168.0.105
# 两者之间的差异是因为 iproute2 版本不一样
root@feiy:/etc/apt# apt-cache policy iproute2
iproute2:
Installed: 4.9.0-1+deb9u1
Candidate: 4.9.0-1+deb9u1
Version table:
*** 4.9.0-1+deb9u1 500
500 http://deb.debian.org/debian stretch/main amd64 Packages
100 /var/lib/dpkg/status
root@feiy:/etc/apt# apt-cache policy iproute2
iproute2:
Installed: 4.20.0-2
Candidate: 4.20.0-2
Version table:
*** 4.20.0-2 500
500 http://deb.debian.org/debian buster/main amd64 Packages
100 /var/lib/dpkg/status
network
docker 是基于 iptables 进行流量的转发,添加了一个虚拟的网卡 docker0 。 如果想从容器内部访问宿主机的 IP,比如从 172.17.0.3 访问宿主机的内网地址 192.168.1.10 , 我们从 tcpdump 在网卡 docker0 抓包可以看到流量。 但是在内网网卡抓包没有结果。猜测原因是:当数据包从网卡 docker0 转发后,直接在内核进入 INPUT 链。所以,如果想访问宿主机的 IP, 需要在 INPUT 添加相关规则,允许访问。 iptables -A INPUT -i docker0 -j ACCEPT
mac 上使用 docker
- volume 的位置和 linux 不同,解决办法如下
1 | cd ~/Library/Containers/com.docker.docker/Data/vms/0/ |
- 如果想从容器内部访问 mac,也和 Linux 不同。详情可以看官网docker mac network 在容器内部可以使用 host.docker.internal 就可以访问到 Mac 宿主机啦。 而在 Linux 机器上, 容器可以直接使用宿主机的 IP 来访问宿主机
NIA_URL=http://host.docker.internal:5000
docker-proxy
can refer this (article)[https://mp.weixin.qq.com/s/S4aMdmQW50HR7Lj2z2-VZQ]1
2
3# /etc/docker/daemon.json
# disable docker-proxy
“userland-proxy”:false
find process
In one hosts, if we have many dockers, sometimes we need find some proceess belong to which docker.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21pstree -laps [pid]
pstree -laps 38564
systemd,1
`-dockerd,171350
`-docker-containe,171362 --config /var/run/docker/containerd/containerd.toml
`-docker-containe,332151 -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/38dfefa95c1f8b4827e0a95834119b3756775d389820ea90d95878d3518eed67 -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
`-smb,332174 /usr/local/bin/smb run -e live -c id -i sg
`-sh,332221 -c gunicorn webapi.wsgi -c webapi/gunicorn_config.py
`-gunicorn: maste,332306
`-gunicorn: worke,38564
|-{gunicorn: worke},38613
|-{gunicorn: worke},83641
|-{gunicorn: worke},83642
|-{gunicorn: worke},83643
|-{gunicorn: worke},83644
|-{gunicorn: worke},83645
|-{gunicorn: worke},83646
`-{gunicorn: worke},83647
# 38dfefa95c1f8b4827e0a95834119b3756775d389820ea90d95878d3518eed67 is container ID
docker-compose
https://wiki.jikexueyuan.com/project/docker-technology-and-combat/commands.html
docker cron
cron failed http://blog.allen-mo.com/2018/04/17/docker_crontab/1
chmod -R 0600 /var/spool/cron/crontabs