上一篇博客中,我提到了如何利用docker update命令为已经运行的Docker容器动态添加新属性,然而这个命令有着很大的局限性,而例如端口映射、IP绑定、卷组挂载等更为常用的操作却没有在该命令中得到支持,因此我们需要使用另外的方法来实现这一目标。

0x01 直接使用update命令

之前的博客中,我已经说明了这一命令的使用方法及其局限性,此处不再赘述。

0x02 重建容器

# 停止旧容器
docker stop $CONTAINER_OLD
# 将旧容器中所有的数据与配置迁移到新容器
docker commit $CONTAINER_OLD $CONTAINER_NEW
# 将新容器携带新配置一同启动
# 此处以新增端口映射为例
docker run -d 8000:80 $CONTAINER_NEW
# 根据需求判断是否删除旧容器
docker stop $CONTAILER_OLD && docker rm $CONTAINER_OLD

重建容器方法适用于新增配置的情况,如果要删除配置,依旧无法解决问题

0x03 修改容器配置文件

# 停止目标容器
docker stop $CONTAINER

# 修改容器的配置文件
vim /var/lib/Docker/containers/$CONTAINER/hostconfig.json
    # 如果是Windows,配置文件在:
    C:\ProgramData\Docker\containers\$CONTAINER\hostconfig.json

# 注意:配置文件格式参考已有容器配置,注意备份!

# 修改完成后保存并重启docker(清除缓存)以及容器
systemctl restart docker
docker start $CONTAINER

0x04 使用第三方工具

由于Docker并不会在执行docker run的时候记录启动命令(这算Docker的一个设计缺陷,完全没有考虑到操作复盘的可能,有机会我可以提交一个Patch看看),因此有大量的第三方工具来帮助从已建立的仓库中逆向出最初的docker run命令,其中最知名的是lavie/runlike

使用方法非常简单:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike $CONTAINER

执行结束后,会出现类似以下的文本:

docker run --name=token-03-web.wutnews.net-php72-apache-work-01 --hostname=b19914483b86 --mac-address=02:42:ac:11:00:22 --env="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" --env="LANG=zh_CN.UTF-8" --env="LANGUAGE=zh_CN:zh" --env="LC_ALL=zh_CN.UTF-8" --volume="/home/htdocs/static.wutnews.net:/assets" --volume="/home/htdocs/web.wutnews.net:/home/htdocs" --volume="/home/htdocs" --volume="/assets" --cap-add="AUDIT_WRITE" --cap-add="CHOWN" --cap-add="DAC_OVERRIDE" --cap-add="FOWNER" --cap-add="FSETID" --cap-add="KILL" --cap-add="MKNOD" --cap-add="NET_BIND_SERVICE" --cap-add="NET_RAW" --cap-add="SETFCAP" --cap-add="SETGID" --cap-add="SETPCAP" --cap-add="SETUID" --cap-add="SYS_CHROOT" --cap-drop="AUDIT_CONTROL" --cap-drop="BLOCK_SUSPEND" --cap-drop="DAC_READ_SEARCH" --cap-drop="IPC_LOCK" --cap-drop="IPC_OWNER" --cap-drop="LEASE" --cap-drop="LINUX_IMMUTABLE" --cap-drop="MAC_ADMIN" --cap-drop="MAC_OVERRIDE" --cap-drop="NET_ADMIN" --cap-drop="NET_BROADCAST" --cap-drop="SYSLOG" --cap-drop="SYS_ADMIN" --cap-drop="SYS_BOOT" --cap-drop="SYS_MODULE" --cap-drop="SYS_NICE" --cap-drop="SYS_PACCT" --cap-drop="SYS_PTRACE" --cap-drop="SYS_RAWIO" --cap-drop="SYS_RESOURCE" --cap-drop="SYS_TIME" --cap-drop="SYS_TTY_CONFIG" --cap-drop="WAKE_ALARM" --network=bridge -p 8018:80 --restart=always --label org.label-schema.schema-version="1.0" --label org.label-schema.license="GPLv2" --label org.label-schema.vendor="CentOS" --label org.label-schema.build-date="20180804" --label org.label-schema.name="CentOS Base Image" --detach=true -t token-03-php72:201901-v4

由于技术限制,无法完美还原生成容器时候的命令,因此这个软件的原理也只是将容器的所有信息映射到建立容器的脚本上,因此在跨设备方面会存在一定的问题,但作为『动态为Docker容器添加新属性』来说,远远足够。

我们可以任意的在这个生成出的命令中新增or删除or修改参数,当修改完成后再重新建立一个新的容器。

尽管最后一种方法并不满足“动态”的要求,但是在灵活度方面却是四种方案里最优的。