Docker练习手册
docker安装
使用aliyun mirrors包安装
#更新本地镜像源
server ~]$ rsync -a 192.168.0.15:/data/source.list/ubuntu.sources /etc/apt/sources.list.d/
#安装必要的工具
server ~]$ apt install -y ca-certificates curl gnupg
#安装GPG证书
server ~]$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
server ~]$ chmod a+r /etc/apt/keyrings/docker.gpg
#写入软件源信息
server ~]$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
#更新并安装docker-ce
server ~]$ apt update
server ~]$ apt install docker-ce -y
#查看docker版本
server ~]$ docker version
#使用内置仓库安装docker
server ~]$ apt -y install docker.io
#删除docker
server ~]$ apt purge docker-ce
server ~]$ rm -rf /var/lib/docker
使用二进制安装
server ~]$ wget https://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-28.1.1.tgz
server ~]$ tar xvf docker-28.1.1.tgz
server ~]$ cp docker/* /usr/bin/
server ~]$ dockerd &> /dev/null &
#创建service文件
server ~]$ cat > /lib/systemd/system/docker.service <<-EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues
still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix://var/run/docker.sock
ExecReload=/bin/kill -s HUP \$MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker
containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
server ~]$ systemctl daemon-reload
server ~]$ systemctl enable --now docker.service
Docker优化配置
vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://n1pi80gc.mirror.aliyuncs.com"
],
"hosts": [
"unix:///var/run/docker.sock",
"tcp://192.168.8.5:2375" #本机host地址
],
"insecure-registries": [
"192.168.8.5"
],
"exec-opts": [
"native.cgroupdriver=systemd"
],
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 5,
"log-opts": {
"max-size": "300m",
"max-file": "2"
}
}
"insecure-registries":列出不使用 HTTPS 的私有仓库地址。配置后,Docker 将允许与这些地址的仓库进行不安全的通信。
#还如果在 daemon.json中配置了hosts,并且在systemd的服务文件中也指定了 -H 参数,会导致冲突。创建此conf文件解决
vim /etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
配置冲突: 在 Ubuntu 系统中,Docker 服务默认使用 -H fd:// 参数启动,这与在 daemon.json 中设置的 "hosts" 配置项冲突。 如果在 daemon.json 中设置了 "hosts",需要移除service文件中的默认 -H 参数。
server ~]$ mkdir -p /etc/systemd/system/docker.service.d
server ~]$ vim /etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
server ~]$ systemctl daemon-reload
server ~]$ systemctl restart docker
server ~]$ docker info #可查看docker的详细信息
docker镜像管理
#搜索镜像
docker search <镜像名>
#拉取镜像
docker pull <镜像名>
#查看本地镜像
docker image ls
docker images --format "{{.Repository}}\t{{.Tag}}\t{{.Size}}"、
#仅查看镜像的仓库名与标签,以":"为分隔符
docker images --format "{{.Repository}}":"{{.Tag}}"
#查看dangling状态的镜像
docker images -f dangling=true
#查看镜像详细信息
docker inspect alpine:3.16.2
#镜像导出
docker save nginx:latest -o nginx.tar
docker save `docker images --format "{{.Repository}}:{{.Tag}}"` | gzip > all.tar.gz
#镜像导入
docker load -i /volume1/Backup/ISO/docker/nginx.tar.gz
docker load < /volume1/Backup/ISO/docker/nginx.tar.gz
#镜像删除
docker image rm -f tomcat #-f强制删除
docker rmi nginx tomcat
#删除dangling状态的镜像
docker rmi -f `docker images -q -f dangling=true`
#修改镜像标签,会生成一个新的镜像
docker tag alpine alpine:3.11
docker容器管理
容器的运行与退出
docker run -it --name a1 alpine:latest sh #-it使用sh以交互式启动docker,--name容器名称为a1
-i(或 --interactive):保持标准输入(STDIN)打开,使您可以与容器内的进程进行交互。
-t(或 --tty):为容器分配一个伪终端(TTY),使输出更符合终端格式,便于阅读。
docker run --rm -it alpine:latest sh #--rm 一次性运行容器,推出后立即删除容器
#-d 以守护模式运行,--restart=always 开机自启,-p 80:80 指定端口映射
docker run -d --restart=always -p 80:80 nginx:latest
docker run -it --privileged centos #--privileged使容器内的root获得宿主机的root权限
#退出容器
exit
crtl+p+q组合键 #从docker中退出,且不停止容器
显示当前存在的容器
docker ps -a -s --format "{{.Names}}\t{{.Size}}"
-a #显示所有容器
-s #显示容器文件大小
-q #显示容器ID
--format #按格式输出信息,注意大小写
docker ps -f 'status=exited' #显示状态为exited的容器
查看容器内的进程
docker top nginx #查看nginx容器内的所有进程
查看容器资源使用情况
docker stats 1e861e9849e1 #以容器ID的方式查看资源使用
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx128m" elasticsearch:7.6.2 #限制内存使用大小
查看容器详细信息
docker inspect 1e861e9849e1 #inspect功能丰富,可查看容器、镜像、网络等
docker inspect --format "{{.Id}}" nginx #可使用format选择性查看
删除容器
docker rm -f `docker ps -a -q` #强制删除所有容器,包含正在运行的容器
docker rm 3a05bbf66dac
docker ps -f status=exited -q | xargs docker rm -f #删除所有停止的容器
容器的启动和停止
docker start|stop|restart|pause|unpause 容器ID
docker pause nginx #暂停nginx
给运行的容器发送信号
docker kill nginx #关闭nginx
docker kill -s 1 web01 #重载配置文件
进入正在运行的容器
docker exec -it nginx bash #使用bash进入nginx容器
docker exex nginx cat /etc/os-release #直接运行命令
port端口
docker port nginx
docker run -p 8080:80/tcp -p 8443:443/tcp -p 53:53/udp --name nginx-test-port6 nginx
#修改容器端口,首先获取容器完整ID
docker inspect --format "{{.Id}}" nginx
#关闭docker服务
systemctl stop docker
#进入容器目录,修改json文件
vim /var/lib/docker/containers/<容器完整ID>/hostconfig.json
#PortBindings后80/tcp对应的是容器内部的80端口,HostPort对应的是映射到宿主机的端口80 修改此处为8000
"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"8000"}]}
systemctl start docker
docker start nginx
容器logs
docker logs -f -t #持续跟踪日志,并加上时间戳
修改hosts文件
docker run -it --rm --add-host www.wangxiaochun.com:6.6.6.6 --add-host www.wang.org:8.8.8.8 busybox #创建时在hosts内添加两个地址
docker run -it --rm --dns 1.1.1.1 --dns 8.8.8.8 centos bash #指定两个DNS地址
容器内和宿主机之间复制文件
docker cp -a 99923:/etc/os-release . #将容器内文件拷出
docker cp /etc/issue 1311:/root/ #将宿主机文件拷至容器
传递环境变量
docker run -e <变量1> -e <变量2> --env-file=env.list mysql:5.7.30
查看docker run启动参数
apt install -y pipx
pipx install runlike
/root/.local/bin/runlike
docker镜像制作管理
#commit制作镜像
docker commit -m "wdnmd" -a "nmlgcb" agitated_ritchie alpine:v1.0
利用 DockerFile 文件执行 docker build 自动构建镜像
#创建dockerfile工作目录
mkdir /data/dockerfile/{web/{apache,nginx,jdk,tomcat},system/{centos,alpine,debian,ubuntu}} -p
FROM 指定基础镜像
LABLE 指定镜像元数据
RUN 用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令。RUN 可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个shell命令通过 && 连接一起成为在一条指令
ENV 设置环境变量
ADD 复制和解包文件
ADD --chown=10:11 files* /somedir/
CMD 容器启动命令
-
RUN 命令是在构建镜像时执行的命令,两者不同。
-
每个 Dockerfile 只能有一条 CMD 命令,如指定了多条,只有最后一条被执行。
-
如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT:入口点 功能类似与CMD,配置容器启动后执行的命令及参数
ARG:在build 阶段指定变量,如果和ENV同名,ENV覆盖ARG变量,可用docker build --build-arg <参数名>=值
VOLUME:匿名卷
EXPOSE:暴露端口
WORKDIR:指定工作目录
ONBUILD:子镜像引用父镜像的指令
USER:指定当前用户
HEALTHCHECK:健康检查
.dockerignore文件
多阶段构建示例,可大幅减少镜像大小
server ]$ cat Dockerfile
FROM alpine:3.21.3 AS builder
LABEL maintainer="wansong <root@884395595@qq.com>"
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories \
&& apk update && \
apk add --no-cache \
build-base \
pcre-dev \
zlib-dev \
openssl-dev \
linux-headers \
curl \
gnupg \
libxslt-dev \
gd-dev \
geoip-dev \
perl-dev \
libedit-dev \
gcc \
make \
wget
ADD nginx-1.26.3.tar.gz /usr/local
RUN cd /usr/local/nginx-1.26.3 && ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && make && make install
FROM alpine:3.21.3
ENV nginx_dir=/apps/nginx
COPY --from=builder /apps/nginx /apps/nginx
RUN apk update && apk --no-cache add tzdata pcre pcre2 \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& addgroup -g 2019 -S nginx \
&& adduser -u 2019 -G nginx -D -S -s /sbin/nologin nginx \
&& chown nginx:nginx -R /apps/nginx \
&& apk del tzdata
EXPOSE 80
COPY nginx.conf /apps/nginx/conf/nginx.conf
COPY entrypoint.sh /
CMD ["/apps/nginx/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/entrypoint.sh"]
docker build -t redis-alpine:v0.1 . #在当前目录构建镜像名为redis-alpine:v0.1的镜像
docker build -f /apps/Dockerfile . #使用/apps目录的Dockerfile构建镜像
#entrypoint脚本内容 自定义变量为host,port
server ]$ cat entrypoint.sh
#!/bin/sh
mkdir -p /apps/nginx/conf/conf.d
cat > /apps/nginx/conf/conf.d/www.conf <<EOF
server {
server_name ${host:-"www.70o70.cn"};
listen ${port:-80};
root /apps/nginx/html;
}
EOF
echo ${host:-"www.70o70.cn"} > /apps/nginx/html/index.html
exec "$@"
#dockerfile目录树
server ]$ tree nginxbase/
nginxbase/
├── Dockerfile
├── entrypoint.sh
├── nginx-1.26.3.tar.gz
└── nginx.conf
server ]$ docker run --name nginx-a -it -p 81:81 -d -e "port=81" -e "host=www.70o70.org" nginx-alpine:v1.4
Docker数据管理
docker run -d -v /data/testdir:/apps/nginx/html
#以只读的方式挂载
docker run -d -v /data/testdir:/data/nginx/html/:ro -p 8004:80 nginx-alpine:1.16.1
#也可以挂载配置文件
docker run -d -v /data/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /data/testapp:/data/tomcat/webapps/testapp -v /data/logs:/apps/tomcat/logs -p 8080:8080 tomcat-web:app1
#创建容器时自动创建命名数据卷
docker run -d -p 8003:80 --name nginx03 -v vol2:/usr/share/nginx/html nginx
#删除指定的命名数据卷
docker volume rm vol1
#清理全部不再使用的数据卷
docker volume prune -f
Docker网络管理
docker run --name testserver --link mysql -it alpine:3.21 sh
#创建使用host模式的容器
docker run -d --network host --name web1 nginx-centos7-base:1.6.1
#创建none模式的无网络容器
docker run -d --network none -p 8001:80 --name web1-none nginx-centos7-base:1.6.1
#创建container模式共享网络的容器
docker run --network container:wordpress --env-file=env --name mysql mysql:8.4.5
#创建自定义网络、查看、删除,自定义网络内的容器间,不使用link也可以直接使用容器名通信
docker network create --subnet 172.27.0.0/16 --gateway 172.27.0.1 test-net
docker inspect test-net
docker network rm test-net
docker network disconnect bridge test2 #断开指定网络连接
#向已创建的容器添加自定义网段,实现容器网络通信
docker network connect test-net test1
#或将已创建容器添加至bridge网络
docker network connect bridge test2
实现跨宿主机间的网络共享
#方式1,需确保两边的容器网络地址不同
apt install bridge-utils
#两台宿主机都将物理网卡接口添加至网桥
brctl addif docker0 eth0 #将docker0网桥挂载eth0
Docker compose
services:
mysql:
image: 192.168.8.5/k8s/mysql:8.4.5
container_name: mysql
volumes:
- /data/sqldata:/var/lib/mysql
environment:
- MYSQL_DATABASE=spug
- MYSQL_USER=spug
- MYSQL_PASSWORD=spug.cc
- MYSQL_ROOT_PASSWORD=spug.cc
env_file:
- ./env
restart: always
networks:
- jpress-net
tomcat:
image: 192.168.8.5/k8s/tomcat-ubuntu:v1.0
container_name: jpress
ports:
- "8080:8080"
depends_on:
- mysql
networks:
- jpress-net
networks:
jpress-net:
driver: bridge
Harbor 仓库
离线部署harbor
#下载Harbor离线安装包
https://github.com/vmware/harbor
tar xzf harbor.tgz -C /apps/
cd /apps/harbor/
cp harbor.yml.tmpl harbor.yml
#修改harbor配置
vim harbor.yml
hostname: 192.168.8.5
harbor_admin_password: 123456
#将HTTPS内容全部注释
bash install.sh #运行install脚本
#生成service文件,需要将所有文件拷贝至/apps/harbor,或修改指定目录
[Unit]
Description=Harbor Cloud Native Registry
Documentation=https://goharbor.io
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/apps/harbor
ExecStart=/usr/bin/docker compose -f docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f docker-compose.yml down -v
ExecStopPost=/usr/bin/docker compose -f docker-compose.yml rm -f
[Install]
WantedBy=multi-user.target
docker拉取harbor提示https未开通,docker添加harbor仓库信任
# 创建docker daemon.json文件
vim /etc/docker/daemon.json
{
"insecure-registries": ["jen.70o70.com", "192.168.8.100"]
}
# 重启docker
sudo systemctl restart docker
docker client配置修改
查看docker优化章节,重启docker服务后 docker login 192.168.8.5
harbor高可用
安装第二台harbor
先新建项目
名称与master harbor项目名称一致,级别为公开
再创建同步目标

创建复制管理规则

在第一台harbor重复此操作
配置nginx反向代理
upstream harbor {
ip_hash;
server 192.168.8.5:80;
server 192.168.8.15:80;
}
server {
listen 80;
server_name harbor.70o70.org;
client_max_body_size 10g;
location / {
proxy_pass http://harbor;
}
}
#客户端docker配置
cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"insecure-registries": ["harbor.70o70.org"]
}
systemctl restart docker
#修改hosts解析域名
docker 资源限制
#内存限制
docker run --rm -it --name c1 -m 200M docker-stress-ng:v1.0
#CPU限制 分配指定可工作的cpu核数
docker run --rm -it --name c1 --cpus 1.5 docker-stress-ng:v1.0 --cpu 4
#分配CPU权重
docker run -it --rm --name c1 --cpu-shares 1000 docker-stress-ng:v1.0 --cpu 4
浙公网安备 33010602011771号