docker部署
[root@server1 ~]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# vim docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
gpgcheck=0
[update]
name=centos
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64/
gpgcheck=0
安装docker-ce
[root@server1 yum.repos.d]# yum install -y docker-ce
启动服务
[root@server1 ~]# systemctl enable --now docker
[root@server1 ~]# docker info
激活内核选项
[root@server1 ~]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
[root@server1 ~]# sysctl --system
[root@server1 ~]# systemctl restart docker
启动容器
[root@server1 ~]# docker run -d --name web1 -p 80:80 nginx
显示激活的容器
[root@server1 ~]# docker ps
访问网页:http://192.168.52.135
删除容器
[root@server1 ~]# docker rm -f web1
查询镜像
[root@server1 ~]# docker search yakexi007
拉取镜像到本地
[root@server1 ~]# docker pull yakexi007/game2048
启动容器
[root@server1 ~]# docker run -d --name web1 -p 80:80 yakexi007/game2048
访问网页:http://192.168.52.135
删除容器
[root@server1 ~]# docker rm -f web1
docker镜像
镜像分层结构
镜像构建
docker commit
[root@server1 ~]# docker run -it --name demo busybox
/ # touch file1
/ # touch file2
ctrl+d: 退出容器后容器自动关闭
ctrl+pq: 退出容器后继续在后台运行
显示所有容器
[root@server1 ~]# docker ps -a
启动容器
[root@server1 ~]# docker start demo
进入容器
[root@server1 ~]# docker attach demo
提交容器变更到新的镜像
[root@server1 ~]# docker commit -m "add files" demo demo:v1
[root@server1 ~]# docker history demo:v1
这种方式不利于安全审计
删除镜像
[root@server1 docker]# docker rmi demo:v1
Dockerfile
[root@server1 ~]# mdkir docker
[root@server1 ~]# cd docker/
[root@server1 docker]# cp ~/nginx-1.23.3.tar.gz .
[root@server1 docker]# vim Dockerfile
FROM centos:7
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
构建镜像
[root@server1 docker]# docker build -t webserver:v1 .
[root@server1 docker]# docker images webserver
[root@server1 docker]# docker history webserver:v1
清理所有停止的容器
[root@server1 docker]# docker container prune
启动容器
[root@server1 docker]# docker run -d --name web1 webserver:v1
查看容器详情
[root@server1 docker]# docker inspect web1
数据卷挂载
自动分配的ip
访问容器
[root@server1 docker]# curl 172.17.0.2
镜像优化
缩减镜像层
[root@server1 docker]# vim Dockerfile
FROM centos:7 as build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t webserver:v2 .
[root@server1 docker]# docker images webserver
多阶段构建
[root@server1 docker]# vim Dockerfile
FROM centos:7 as build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all
FROM centos:7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t webserver:v3 .
[root@server1 docker]# docker images webserver
使用最精简的基础镜像
导入基础镜像
[root@server1 ~]# docker load -i base-debian11.tar
[root@server1 ~]# mkdir new
[root@server1 ~]# cd new/
[root@server1 new]# vim Dockerfile
FROM nginx:1.23.3 as base
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
cp -a --parents /usr/share/nginx /opt && \
cp -a --parents /var/log/nginx /opt && \
cp -aL --parents /var/run /opt && \
cp -a --parents /etc/nginx /opt && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/sbin/nginx /opt && \
cp -a --parents /usr/sbin/nginx-debug /opt && \
cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
FROM gcr.io/distroless/base-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@server1 new]# docker build -t webserver:v4 .
[root@server1 new]# docker images webserver
[root@server1 new]# docker run -d --name web1 webserver:v4
[root@server1 new]# curl 172.17.0.2
Docker仓库
registry私有仓库
官网: Deploy a registry server | Docker Docs
拉取registry镜像
[root@server1 ~]# docker pull registry
运行registry仓库
[root@server1 docker]# docker run -d -p 5000:5000 --restart=always --name registry registry
上传镜像
[root@server1 ~]# docker tag nginx:latest localhost:5000/nginx:latest
[root@server1 ~]# docker push localhost:5000/nginx
[root@server1 ~]# curl localhost:5000/v2/_catalog
{"repositories":["nginx"]}
下载镜像
[root@server1 ~]# docker pull localhost:5000/nginx
insecure registry
配置使用非加密端口
[root@server2 ~]# vim /etc/docker/daemon.json
{
"insecure-registries" : ["http://192.168.52.135:5000"]
}
[root@server2 docker]# systemctl restart docker
拉取镜像
[root@server2 docker]# docker pull 192.168.52.135:5000/nginx
仓库加密
升级软件包
[root@server1 ~]# yum install -y openssl11-1.1.1k-4.el7.x86_64.rpm openssl11-libs-1.1.1k-4.el7.x86_64.rpm
添加域名解析
[root@server1 ~]# vim /etc/hosts
192.168.52.135 docker reg.westos.org
[root@server1 ~]# mkdir certs
[root@server1 ~]# openssl11 req -newkey rsa:4096 -nodes -sha256 -keyout certs/westos.org.key -addext "subjectAltName = DNS:reg.westos.org" -x509 -days 365 -out certs/westos.org.crt
域名保持一致
[root@server1 ~]# docker run -d -p 443:443 --restart=always --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/westos.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/westos.org.key registry
部署客户端证书,不然会报错
[root@server1 ~]# docker tag nginx:latest reg.westos.org/nginx:latest
[root@server1 ~]# docker push reg.westos.org/nginx:latest
[root@server1 ~]# mkdir -p /etc/docker/certs.d/reg.westos.org/
[root@server1 ~]# cp /root/certs/westos.org.crt /etc/docker/certs.d/reg.westos.org/ca.crt
验证
[root@server1 ~]# docker push reg.westos.org/nginx:latest
[root@server1 ~]# curl -k https://reg.westos.org/v2/_catalog
仓库认证
[root@server1 ~]# yum install -y httpd-tools
[root@server1 ~]# mkdir auth
[root@server1 ~]# htpasswd -Bc auth/htpasswd admin
New password:
Re-type new password:
Adding password for user admin
第二次添加不要加“-c”选项,不然会覆盖
[root@server1 ~]# htpasswd -B auth/htpasswd wxh
New password:
Re-type new password:
Adding password for user wxh
[root@server1 ~]# cat auth/htpasswd
删除registry,重建
[root@server1 ~]# docker rm -f registry
[root@server1 ~]# docker run -d -p 443:443 --restart=always --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/westos.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/westos.org.key -v /root/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry
登录仓库,不然无法上传下载
[root@server1 ~]# docker login reg.westos.org
[root@server1 ~]# cat .docker/config.json
验证
[root@server1 ~]# docker tag busybox:latest reg.westos.org/busybox:latest
[root@server1 ~]# docker push reg.westos.org/busybox:latest
[root@server1 ~]# curl -k https://reg.westos.org/v2/_catalog -u admin:westos
{"repositories":["busybox","nginx"]}
登出
[root@server1 ~]# docker logout reg.westos.org
server2上移除非安全仓库设置
[root@server2 docker]# mv daemon.json /mnt/
[root@server2 docker]# systemctl restart docker
添加解析
[root@server2 ~]# vim /etc/hosts
192.168.52.135 docker reg.westos.org
拷贝证书
[root@server1 ~]# cd /etc/docker/
[root@server1 ~]# scp -r certs.d/ server2:/etc/docker/
登录远程仓库
[root@server2 docker]# docker login reg.westos.org
拉取镜像
[root@server2 docker]# docker pull reg.westos.org/busybox
harbor企业级私有仓库
删除之前部署的registry,不然会冲突
[root@server1 ~]# docker rm -f registry
[root@server1 ~]# tar zxf harbor-offline-installer-v2.5.0.tgz
[root@server1 ~]# cd harbor/
[root@server1 harbor]# cp harbor.yml.tmpl harbor.yml
[root@server1 harbor]# vim harbor.yml
hostname: reg.westos.org
certificate: /data/certs/westos.org.crt
private_key: /data/certs/westos.org.key
harbor_admin_password: westos
拷贝证书
[root@server1 ~ ]# mkdir /data
[root@server1 ~ ]# cp -r certs /data
部署docker-compose
[root@server1 ~]# mv docker-compose-linux-x86_64-v2.5.0 /usr/local/bin/docker-compose
[root@server1 ~]# chmod +x /usr/local/bin/docker-compose
部署harbor
[root@server1 harbor]# ./install.sh
使用浏览器登录仓库 用户名:admin 密码是上面配置文件设置的westos
https://192.168.52.135
上传镜像,首先需要执行docker login reg.westos.org
[root@server1 ~]# docker tag busybox:latest reg.westos.org/library/busybox:latest
[root@server1 ~]# docker tag nginx:latest reg.westos.org/library/nginx:latest
[root@server1 ~]# docker push reg.westos.org/library/nginx:latest
[root@server1 ~]# docker push reg.westos.org/library/busybox:latest
配置默认仓库
[root@server2 ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://reg.westos.org"]
}
[root@server2 ~]# systemctl restart docker
library项目中的镜像下载时可以直接写镜像名称
[root@server2 ~]# docker pull nginx
公共仓库支持匿名拉取
创建私有仓库
新建用户
授权维护私有仓库
私有仓库上传下载都需要认证,并且还要指定仓库域名
[root@server1 ~]# docker tag ubuntu:latest reg.westos.org/westos/ubuntu:latest
[root@server1 ~]# docker push reg.westos.org/westos/ubuntu:latest
[root@server2 ~]# docker login reg.westos.org
[root@server2 ~]# docker pull reg.westos.org/westos/ubuntu
删除harbor仓库
[root@server1 harbor]# docker-compose down
Docker网络
原生网络
[root@server1 harbor]# docker network ls
默认使用桥接模式,桥接到docker0上
[root@server1 ~]# docker run -d --name demo nginx
[root@server1 ~]# yum install -y bridge-utils
[root@server1 ~]# brctl show
host模式,容器和宿主机共享同一网络栈,不会新建虚拟网卡
[root@server1 ns]# docker run -it --rm --network host busybox
none禁用网络,只用回环接口
[root@server1 harbor]# docker run -it --rm --network none busybox
自定义网络
[root@server1 ~]# docker network create my_net1
自定义网络地址段
[root@k8s1 ~]# docker network create --subnet 10.0.0.0/24 --gateway 10.0.0.1 my_net2
自定义网络内嵌dns解析
[root@server1 ~]# docker run -d --name web1 --network my_net1 nginx
[root@server1 ~]# docker run -it --rm --network my_net1 busybox
不同网络之间是被隔离的,默认不能通信
[root@server1 ~]# docker run -it --rm --network my_net2 busybox
不同网络之间的通信需要附加虚拟网卡
[root@server1 ~]# docker run -it --rm --network my_net2 --name demo busybox
ctrl+pq 快捷键退出容器终端
把demo接入到my_net1网络
[root@server1 ~]# docker network connect my_net1 demo
再进入容器
[root@server1 ~]# docker attach demo
joined容器
两个容器共享一个网络栈
[root@server1 ~]# docker run -it --rm --network container:web1 --name web2 busybox
Docker数据卷
bind mount
[root@server1 ~]# docker run -it --rm -v /tmp/data1:/data1 -v /tmp/data2:/data2:ro -v /etc/passwd:/mnt/passwd:ro busybox
docker managed volume
[root@server1 ~]# docker run -d --name web1 webserver:v3
[root@server1 ~]# docker inspect web1
[root@server1 ~]# cd "/var/lib/docker/volumes/9e6528410eb82a00f89bd1eb5cdda034bb1fbbd0eab1aa36f5ec08fc521a5fae/_data"
[root@server1 _data]# ls
50x.html index.html
docker managed volume 会复制目标挂载点的数据
查询docker managed volume
[root@server1 volumes]# docker volume ls
清理所有数据卷,在清理前需要先删除容器,释放对数据卷的占用
[root@server1 volumes]# docker volume ls | grep -v DRIVER | awk '{system("docker volume rm "$2"")}'
创建数据卷
[root@server1 ~]# docker volume create vol1
vol1
[root@server1 ~]# docker volume ls
DRIVER VOLUME NAME
local vol1
[root@server1 ~]# docker volume inspect vol1
使用bind mount方式挂载数据卷
[root@server1 ~]# docker run -d --name web1 -v vol1:/usr/local/nginx/html webserver:v3
还能在挂载时控制权限
[root@server1 ~]# docker rm -f web1
web1
[root@server1 ~]# docker run -d --name web1 -v vol1:/usr/local/nginx/html:ro webserver:v3
共享卷
[root@server1 ~]# docker create -v /tmp/data1:/data1:rw -v /tmp/data2:/data2:ro -v /etc/passwd:/mnt/passwd:ro --name datavol busybox
[root@server1 ~]# docker run -it --rm --volumes-from datavol busybox
Docker安全
cgroup
cpu资源限制
[root@server1 cpu]# docker run -it --rm --cpu-period 100000 --cpu-quota 20000 ubuntu
root@433a1612a171:/# dd if=/dev/zero of=/dev/null &
容器会直接调用cgroup
cpu优先级
[root@server1 cpu]# docker run -it --rm ubuntu
root@0280fc49f2d0:/# dd if=/dev/zero of=/dev/null &
[root@server1 cpu]# docker run -it --rm --cpu-shares 100 ubuntu
root@b75b4d5066b8:/# dd if=/dev/zero of=/dev/null &
测试时只保留一个cpu核心可用,只有争抢cpu资源时优先级才会生效
[root@server1 cpu1]# pwd
/sys/devices/system/cpu/cpu1
[root@server1 cpu1]# echo 0 > online
内存资源限制
[root@server1 ~]# docker run -d --name demo --memory 200M --memory-swap=200M nginx
[root@server1 memory]# pwd
/sys/fs/cgroup/memory
[root@server1 memory]# mkdir x1
[root@server1 memory]# cd x1/
[root@server1 x1]# echo 209715200 > memory.limit_in_bytes
[root@server1 x1]# yum install -y libcgroup-tools.x86_64
[root@server1 x1]# cd /dev/shm/
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300
[root@server1 shm]# free -m
total used free shared buff/cache available
Mem: 1980 187 1080 206 712 1389
Swap: 2047 103 1944
多出的100m会写入swap
[root@server1 shm]# cd /sys/fs/cgroup/memory/x1/
[root@server1 x1]# echo 209715200 > memory.memsw.limit_in_bytes
[root@server1 x1]# cd -
/dev/shm
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300
Killed
控制用户内存
[root@server1 shm]# useradd wxh
[root@server1 shm]# vim /etc/cgrules.conf
wxh memory x1/
[root@server1 shm]# systemctl start cgred.service
[root@server1 shm]# su - wxh
[wxh@server1 ~]$ cd /dev/shm/
[wxh@server1 shm]$ dd if=/dev/zero of=bigfile bs=1M count=200
Killed
磁盘io限制
[root@server1 ~]# docker run -it --rm --device-write-bps /dev/sda:30MB ubuntu
root@3226b0fc6231:/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 3.31722 s, 31.6 MB/s
lxcfs隔离
[root@server1 ~]# yum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm
[root@server1 ~]# lxcfs /var/lib/lxcfs &
[root@server1 ~]# 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 \
> -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
> -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
> -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
> ubuntu
root@45edbc92cc1d:/# free -m
total used free shared buff/cache available
Mem: 256 0 255 9 0 255
Swap: 256 0 256
容器特权
默认容器内的用户是受限的
[root@server1 ~]# docker run -it --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # id
uid=0(root) gid=0(root) groups=0(root),10(wheel)
/ # ip link set down eth0
ip: SIOCSIFFLAGS: Operation not permitted
/ # fdisk -l
开启容器特权
[root@server1 ~]# docker run -it --rm --privileged busybox
/ # fdisk -l
Disk /dev/sda: 20 GB, 21474836480 bytes, 41943040 sectors
2610 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/sda1 * 0,32,33 130,170,40 2048 2099199 2097152 1024M 83 Linux
/dev/sda2 130,170,41 1023,254,63 2099200 41943039 39843840 18.9G 8e Linux LVM
Disk /dev/dm-0: 17 GB, 18249416704 bytes, 35643392 sectors
2218 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Disk /dev/dm-0 doesn't contain a valid partition table
Disk /dev/dm-1: 2048 MB, 2147483648 bytes, 4194304 sectors
261 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Disk /dev/dm-1 doesn't contain a valid partition table
/ # ip link set down eth0
/ # ip link set up eth0
设置容器白名单
[root@server 1 ~]# docker run -it --rm --cap-add=NET_ADMIN busybox
/ # fdisk -l
/ # ip a a 10.0.0.1/24 dev eth0
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet 10.0.0.1/24 scope global eth0
valid_lft forever preferred_lft forever
/ # ip a d 10.0.0.1/24 dev eth0
/ # ip a