容器

为正在运行的容器添加端口映射

引言


有时想在运行的容器中再添加一个端口,特别是使用 nginx docker 时,刚开始没有预留足够的端口映射,后来又要添加几个项目,还不想启动多个nginx的容器,那么就一心想添加几个端口映射。

比如我想添加 宿主机的 [18080] 到 docker 的 [8080] 端口。

方法一:删除原来容器,重新run一个容器。


记得重新run容器的时候将需要映射的端口加上;这种方法只适合没有状态的容器或者没有持久化的容器,毕竟重建后的容器是一个全新的,之前配置的东西全还原了。也可以将之前容器中的数据通过docker cp命令拷贝出来,再拷贝进新的容器中。

优缺点:优点是简单快捷,在测试环境使用较多。缺点是如果是数据库镜像,那重新建一个又要重新配置一次,就比较麻烦了。

方法二:修改容器的配置文件,需要重启docker进程


要修改 /var/lib/docker/containers/[containerId] 目录下,hostconfig.json 和 config.v2.json 两个配置文件。

1.停止docker 服务

一定要先停 docker 服务,要不修改无效,还会被刷回去。

systemctl stop docker

执行 systemctl stop docker 后提示“Warning: Stopping docker.service, but it can still be activated by: docker.socket”

这是docker在关闭状态下被访问自动唤醒机制,很人性化,即这时再执行任意docker命令会直接启动

注:如果真的不希望docker被访问自动唤醒,执行 systemctl stop docker 后再执行systemctl stop docker.socket即可

停止 docker 服务,所有的 docker 容器也自动停了。

2. 修改配置文件

容器的配置文件:/var/lib/docker/containers/[hash_of_the_container]/hostconfig.json

容器的配置文件:/var/lib/docker/containers/[hash_of_the_container]/config.v2.json

其中的hash of the container是docker镜像的hash值,可以通过docker ps或者docker inspect containername查看。(CONTAINER ID就可以看出来)

根据你的实际容器id去查找

2.1 修改 hostconfig.json文件

hostconfig.json 文件用于描述容器与宿主机之间的交互信息,包括端口映射、挂载卷等。其中的 PortBindings 字段指定容器内部端口与宿主机端口的映射关系,用于实现容器内部服务的外部访问。

只需给 PortBindings 选项添加一项 “8080/tcp”:[{“HostIp”:””,”HostPort”:”18080″}]

{
    # ... 省略其他不相关
    
    "PortBindings":{
        "22/tcp":[{"HostIp":"","HostPort":"5022"}],
        
        # 添加新的映射代码
        "8080/tcp":[{"HostIp":"","HostPort":"18080"}]
    },
    
    # ... 省略其他不相关
}

2.2 修改config.v2.json 文件

config.v2.json 文件用于描述容器的配置信息,包括容器的命令、环境变量、暴露的端口等。其中的 Ports 字段指定容器内部正在监听的端口,但并不表示这些端口会映射到宿主机上。

    # ... 省略其他不相关
    
    # 对外暴露端口
    "ExposedPorts":{
        "22/tcp":{},
        
        # 添加新的映射代码
        "8080/tcp":{}
    }
    
    # ... 省略其他不相关
    
    # 如果Ports字段本来就是空,那就不用修改
    "Ports": {
        "22/tcp": [{"HostIp": "0.0.0.0","HostPort": "5022"}],
        
         # 添加新的映射代码
        "8080/tcp": [{"HostIp": "0.0.0.0","HostPort": "18080"}],
    }
    
    # ... 省略其他不相关
docker 配置文件 config.v2.json 中 Ports 和 hostconfig.json 中 PortBindings 区别:

config.v2.json 主要用于描述容器的配置信息,Ports 字段用于指定容器内部正在监听的端口,即容器内的端口。因为 ExposedPorts 字段已经对外暴露了端口,所以如果宿主机所有ip都可以映射到暴露的端口,那么此处 Ports 字段就可以为空。如果需要设置对应的IP那么就应该设置。

hostconfig.json 主要用于描述容器与宿主机之间的交互信息, PortBindings 字段用于指定容器内部端口与宿主机端口的映射关系,用于实现容器内部服务的外部访问。

由于 Ports 和 PortBindings 都涉及容器的端口映射,有时候可能会造成一些冗余和混淆。一般来说,在 Docker 中,推荐使用 PortBindings 来指定容器的端口映射,而将 config.v2.json 中的 Ports 字段留空或不指定。这样可以更清晰地表达容器与宿主机之间的端口映射关系,减少重复配置。

优缺点:这个方法的优点是没有副作用,操作简单。缺点是需要重启整个docker服务,如果在同一个宿主机上运行着多个容器服务的话,就会影响其他容器服务。

3.重启 docker服务

systemctl restart docker

方法三:使用docker commit将当前容器创建为一个镜像,在启动这个镜像时映射新的端口号出来。


docker commit:把一个容器的文件改动和配置信息commit到一个新的镜像。这个在测试的时候会非常有用,把容器所有的文件改动和配置信息导入成一个新的docker镜像,然后用这个新的镜像重起一个容器,这对之前的容器不会有任何影响。

1、停止docker容器

docker stop container01 

2、commit该docker容器

docker commit container01 new_image:tag 

3、用前一步新生成的镜像重新起一个容器

docker run --name container02 -p 80:80 new_image:tag 

优缺点:这种方式的优点是不会影响统一宿主机上的其他容器,缺点是管理起来显得比较乱,没有第二种方法那么直观。