Docker
Docker
安装
从 DaoCloud 下载并安装(推荐,速度快)
- 安装 docker
curl -sSL https://get.daocloud.io/docker | sh - 安装 docker-compose
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose - 配置 docker 镜像站
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
- 安装 docker
Debian/Ubuntu 环境安装 docker 社区版
新增 docker apt repository
# curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - # sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"安装 docker-ce
sudo apt-get update
sudo apt-get install docker-ce非官方源是不可信任的,可能会出现异常 “W: GPG error: https://download.docker.com trusty Release: The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8”,解决办法是导入该源的公钥
gpg --keyserver download.docker.com --recv 7EA0A9C3F273FCD8 && gpg --export --armor 7EA0A9C3F273FCD8 | sudo apt-key add -
或
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-get update启动 docker 服务
service docker start
停止 docker 服务service docker stop
-
下载 registry 镜像
docker pull registry创建一个 registry 的容器并运行(”-p 5000:5000” 表示将容器内部的 5000 端口映射到宿主机的 5000 端口)
docker run -d -p 5000:5000 registrydocker run \ -d \ # 作为 daemon 进程启动,即后台启动 -v /myrepo:/var/lib/registry \ # 将容器 /var/lib/registry 目录映射到宿主机的 /myrepo,用于存放镜像数据 -p 5000:5000 \ # 将容器的 5000 端口映射到 Host 的 5000 端口(5000 是 registry 服务端口) registry:latest验证 registry 容器是否启动成功
curl http://127.0.0.1:5000/v2/_catalog使用 registry 管理仓库和镜像
- 上传镜像
- 使用 tag 命令让本地镜像 hello-world 指向到 registry 仓库中
docker tag hello-world localhost:5000/hello-world:latest - 推送到 registry 仓库中
docker push localhost:5000/hello-world
- 使用 tag 命令让本地镜像 hello-world 指向到 registry 仓库中
- 下载镜像
docker pull localhost:5000/hello-world
- 上传镜像
开启 TLS 认证
启动服务
# 生成证书 openssl req -newkey rsa:4096 -nodes -sha256 -keyout myhub.key -subj "/CN=myhub.com" -x509 -days 365 -out myhub.crt # 生成账号密码 zhangsan/123456 docker run --rm --entrypoint htpasswd httpd:2 -Bbn zhangsan 123456 > htpasswd # 启动 registry 容器 docker run -d -p 5000:5000 --restart=always --name registry \ # -v /myrepo:/var/lib/registry \ -v $(pwd):/certs \ # 将证书和私钥文件挂载进容器内 /certs 目录下 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/myhub.crt \ # 指定(容器内的)证书和私钥文件路径 -e REGISTRY_HTTP_TLS_KEY=/certs/myhub.key \ -v $(pwd):/auth \ # 将账号密码文件挂载进容器内 /auth 目录下 -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ # 指定(容器内的)账号密码文件路径 registry配置访问
# 配置 host echo "127.0.0.1 myhub.com" >> /etc/hosts # 验证服务是否启动 curl --cacert myhub.crt https://myhub.com:5000/v2/_catalog # 下发证书 mkdir -p /etc/docker/certs.d/myhub.com\:5000 cp myhub.crt /etc/docker/certs.d/myhub.com\:5000 # 账号密码登录 docker login myhub.com:5000 # username: zhangsan # password: 123456 # 上传镜像 docker tag hello-world myhub.com:5000/hello-world:latest docker push myhub.com:5000/hello-world # 下载镜像 docker pull myhub.com:5000/hello-world # 退出登录 docker logout myhub.com:5000
使用 Harbor 搭建 docker 私有 hub
- 搭建
- 配置域名访问,如 https://www.mydockerhub.com
- 上传镜像
- 在 /etc/docker/certs.d 目录下配置 Harbor 服务的公钥证书
cd /etc/docker/certs.d mkdir www.mydockerhub.com cd www.mydockerhub.com openssl s_client -showcerts -connect www.mydockerhub.com:443 < /dev/null 2> /dev/null | openssl x509 -outform PEM > www.mydockerhub.com.crt - 登录 Harbor 服务
docker login www.mydockerhub.com - 推送镜像
docker push www.mydockerhub.com/hello-world:latest
- 在 /etc/docker/certs.d 目录下配置 Harbor 服务的公钥证书
-
修改 daemon 配置文件 /etc/docker/daemon.json 来使用加速器(其中 “https://0cx54rhx.mirror.aliyuncs.com" 为已申请的专属加速器地址)
tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://0cx54rhx.mirror.aliyuncs.com"] } EOF重启 docker 服务
# ubuntu service docker restart # centos # systemctl restart docker # 如果是在容器中(如 docker:dind)重启 docker 服务,则直接在宿主机上执行 docker restart 重启容器即可
开启 docker 实验功能
- 修改配置文件 /etc/docker/daemon.json,在
/节点下新增配置项"experimental": true - 重启 docker 服务
- 修改配置文件 /etc/docker/daemon.json,在
使用
查看 docker 版本信息
docker version
查看 docker 系统的信息
docker info镜像(Image)管理
# 列出远程仓库 Docker Hub 中所有名称为 ubuntu 的镜像 docker search ubuntu # 从远程仓库 Docker Hub 中下载名称为 ubuntu 的镜像到本地 docker pull ubuntu # 推送/发布镜像至远程仓库 Docker Hub 中 docker push new_image_name # 列出本地仓库中所有的 docker 镜像 docker images # 删除本地仓库中名称为 ubuntu 的镜像 docker rmi ubuntu # # 删除本地仓库中所有镜像 # docker rmi $(docker images -q) # 生成一个镜像 ubuntu 的实例(即容器),并执行该容器中的 /bin/bash,从而交互式进入到该容器中(键入 Ctrl + P + Q 键退出容器但不停止,键入 Ctrl + D 键或执行命令 exit 即可退出容器且停止容器) docker run -it ubuntu /bin/bash # # 创建一个镜像 ubuntu 的容器,新建的容器处于停止状态,可以使用 docker start 命令启动 # docker create -it ubuntu # # 生成一个新的容器,并运行命令 ping www.google.com # docker run ubuntu ping www.google.com # # 通过 “-v” 参数可以支持把一个宿主机上的目录挂载到容器中 # docker run -it -v /home/downloads:/usr/downloads ubuntu /bin/bash # 使用 "--entrypoint bash" 覆盖容器中 entrypoint 的默认启动命令,可用于启动因原 entrypoint 命令存在问题而导致无法启动容器的镜像 # docker run --entrypoint bash -it nginx # 创建一个 redis 的只读容器 # docker run -- read-only redis # 根据当前目录下的文件 Dockerfile 构建出一个名称为 IMAGE[:VERSION] 的镜像 docker build -t IMAGE[:VERSION] . docker build --squash -t IMAGE[:VERSION] . # 参数 "--squash" 表示压缩镜像,需要开启 docker 实验功能 # # 查看指定镜像的创建历史 # docker history IMAGE[:VERSION] # 打包镜像 ubuntu,并导出到文件 ubuntu.tar 中 docker save -o ubuntu.tar ubuntu # 从文件 ubuntu.ta 中导入镜像到本地仓库中 docker load -i ubuntu.tar # docker load < ubuntu.tar容器(Container)管理
# 列出本地所有正在运行的容器 docker ps # 列出本地所有的容器 docker ps -a # # 列出本地所有的容器和体积大小 # docker ps -as # 登录一个正在执行的容器 docker attach [CONTAINER ID|NAMES] # 启动容器 # 其中 CONTAINER ID 为容器 ID、NAMES 为容器名称,可由 docker ps 查得。如启动 ID 为 5bf9b7645ed2 的容器:docker start 5bf9b7645ed2 docker start [CONTAINER ID|NAMES] # 停止容器 # 如停止 NAMES 为 focused_bardeen 的容器:docker stop focused_bardeen docker stop [CONTAINER ID|NAMES] # 杀死容器 docker kill [CONTAINER ID|NAMES] # docker kill $(docker ps -a -q) # 杀死所有正在运行的容器 # 重启容器 docker restart [CONTAINER ID|NAMES] # 删除容器 docker rm [CONTAINER ID|NAMES] # docker rm $(docker ps -a -q) # 删除所有已经停止的容器 # 从一个容器中取日志 docker logs [CONTAINER ID|NAMES] # 列出一个容器里面被改变的文件或者目录,list 列表会显示出三种事件,A 增加的,D 删除的,C 被改变的 docker diff [CONTAINER ID|NAMES] # 显示一个运行的容器里面的进程信息 docker top [CONTAINER ID|NAMES] # 从容器里面拷贝文件/目录到本地一个路径 # docker cp [CONTAINER ID|NAMES]:/container_path to_path docker cp /sbin/ifconfig 5bf9b7645ed2:/sbin # 使用已启动的容器,运行命令 ping www.google.com docker exec 5bf9b7645ed2 ping www.google.com # 使用已启动的容器,交互运行 /bin/sh docker exec -it b7542f84a6c3 /bin/sh # 导出容器到文件 /tmp/container01.tar 中 docker export [CONTAINER ID|NAMES] > /tmp/container01.tar # 从文件 /tmp/container01.tar 中导入容器,并设置其 NAMES 为 focused_bardeen cat /tmp/container01.tar | docker import - focused_bardeen # # 导出容器并重新导入到镜像中,可用于压缩镜像。ref https://blog.csdn.net/qq_36763896/article/details/53293088 # docker export <container id> | docker import - <image name> # 将容器 a404c6c174a2 保存为新的镜像 hello,并添加提交人信息和说明信息 docker commit -a "author" -m "describe" a404c6c174a2 hello:v1 # docker commit --change='ENTRYPOINT ["entrypoint.sh"]' a404c6c174a2 hello:v1 # docker commit -c 'ENV JAVA_HOME=/opt/jdk' -c 'ENV PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$JAVA_HOME/bin' -c 'ENTRYPOINT service ssh start && /bin/bash' a404c6c174a2 ubuntu-jdk-ssh # 查看容器端口映射 docker port a404c6c174a2 docker port a404c6c174a2 8080-
# 创建一个 overlay 网络 overlay1 docker network create -d overlay --attachable overlay1 # 查看网络 overlay1 的信息 network inspect overlay1# 查看 NAT 表中的 PREROUTING 链(iptables 将满足条件的数据都转发到了 DOCKER 链上去了) iptables -t nat --list-rules PREROUTING # 查看 NAT 表中的 DOCKER 链 iptables -t nat --list-rules DOCKER # 查看容器的 ip docker inspect <容器id> | grep '"IPAddress":' | grep -o -E [0-9.]+ | head -n 1 # 端口映射 iptables -t nat -A DOCKER -p tcp --dport <容器外部端口> -j DNAT --to-destination <容器ip>:<容器内部端口> # iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source <容器ip> --destination <容器ip> --dport <容器内部端口> iptables -A DOCKER -j ACCEPT -p tcp --destination <容器ip> --dport <容器内部端口> # 取消端口映射规则 iptables -t nat -D DOCKER -p tcp -d 0/0 --dport <容器外部端口> -j DNAT --to-destination <容器ip>:<容器内部端口> iptables -D DOCKER -j ACCEPT -p tcp --destination <容器ip> --dport <容器内部端口> 删除那些已停止的容器、dangling 镜像、未被容器引用的 network 和构建过程中的 cache
docker system prune
强制清理
docker system prune --all --force --volumes资源限制
docker run --rm -it \ --cpu-period=100000 --cpu-quota=20000 \ # 每 100 毫秒(即 100000 微秒)内,运行进程使用的 cpu 时间最多为 20 毫秒 --cpuset-cpus="1" \ # 指定运行容器编号为 1 的 cpu。https://m.jb51.net/article/135395.htm?from=singlemessage -m 50M --memory-swap 50M \ # 容器可以使用 50M 的物理内存,且不能使用 swap。https://www.cnblogs.com/sparkdev/p/8032330.html --device-write-bps /dev/sda:30MB \ # 限制容器写 /dev/sda 的速率为 30MB/s。http://m.hangge.com/news/cache/detail_2413.html u-stress:latest /bin/bash stress -c 4 # 启动压力测试示例
# 创建一个(虚拟的)网络接口名称为 docker1、网络 NAME 为 bridge1、子网网段为 10.0.1.* 的网桥 docker network create -o "com.docker.network.bridge.name"="docker1" --subnet=10.0.1.0/24 bridge1 # 停用网络接口 docker1 # ifconfig docker1 down #apt-get install bridge-utils #brctl delbr docker1 # 创建一个镜像为 ubuntu、网桥为 bridge1、ip 地址为 10.0.1.2、名称为 client1 的容器,并将宿主机目录 /sbin 挂载到容器中目录 /sbin 下,交互式启动容器中 /bin/bash docker run -it --network bridge1 --ip 10.0.1.2 --name client1 -v /sbin:/sbin ubuntu /bin/bash构建镜像
构建极简镜像(镜像中应用存在依赖关系)
例如,基于一个空的基础镜像完成一个 /bin/hello 的镜像查看 /bin/hello 的依赖库,并将 /bin/hello 以及其依赖的动态库,打包至文件 rootfs.tar.gz 中
ldd /bin/hello | perl -p -e 's#^\s*(\S+ => )?(/\S+) \(0x[0-9a-z]+\)$#$2#g' | grep -v 'linux-vdso' | sed '$a/bin/hello' | xargs tar zcvf rootfs.tar.gz编辑文件 Dockerfile 构建镜像
FROM scratch ADD rootfs.tar.gz / # COPY redis.conf /etc/redis/redis.conf # EXPOSE 6379 # CMD ["redis-server"] CMD ["/bin/hello"]构建镜像 hello
docker build -t hello .
构建简单镜像(镜像中应用无依赖)
编辑文件 Dockerfile
FROM scratch ADD hello / CMD ["/hello"]Docker registry 中,有一个被称为 scratch 的使用空 tar 文件构建的特殊镜像
tar cv --files-from /dev/null | docker import - scratch
基于该映像可构建新的无冗余的镜像构建镜像 hello
docker build -t hello .
-
FROM gcc AS mybuildstage COPY hello.c . RUN gcc -o hello hello.c FROM alpine COPY --from=mybuildstage hello . CMD ["./hello"]