docker重启配置生效的测试

docker重启配置生效的测试及理解

最近用docker安装一些安全工具,修改容器配置文件如何生效一直有点困惑,以下以nginx容器为例子,测试从镜像,容器,docker-compose编排以及nginx的配置修改,如何重启才能生效。

先说结论

  • 修改Dockerfile只能删除镜像和容器,并重新生成镜像才能生效
  • 修改docker-compose.yml只能先down再up才能生效,其它重启操作都无效
  • 修改nginx配置,任何重启操作都可以生效

首先创建一个nginx

使用Dockerfile创建一个nginx镜像,然后构建镜像并运行它

1
2
3
4
FROM nginx
docker build -t test-nginx:latest .
docker run -itd --name test-nginx test-nginx:latest /bin/bash
docker ps | grep test-nginx

测试1:修改Dockerfile如何才能生效

Dockerfile增加一行暴露443端口,并直接重启容器

1
2
FROM nginx
EXPOSE 443
1
2
docker restart test-nginx
docker ps | grep test-nginx

可以看到443端口没有生效

删除容器再启动

1
2
3
4
docker stop test-nginx
docker rm test-nginx
docker run -itd --name test-nginx test-nginx:latest /bin/bash
docker ps | grep test-nginx

同样可以看到443端口没有生效

删除容器和镜像再启动

1
2
3
4
5
6
docker stop test-nginx
docker rm test-nginx
docker rmi test-nginx:latest
docker build -t test-nginx:latest .
docker run -itd --name test-nginx test-nginx:latest /bin/bash
docker ps | grep test-nginx

可以看到这次443端口配置已经生效

总结

由于Dockerfile是用来生成镜像的,一旦镜像生成,后面的操作都与它无关了,修改Dockerfile就要删除镜像重新生成才能生效

测试2:修改Dockerfile如何才能生效

先创建docker-compose.yml,用来运行容器并只对外暴露8080端口,配置如下

1
2
3
4
5
6
7
version: "3.8"
services:
test-nginx:
container_name: test-nginx
image: test-nginx:latest
ports:
- 8080:80

先把上面创建的容器先删除,然后使用docker-compose来启动容器

1
2
3
4
docker stop test-nginx
docker rm test-nginx
docker-compose up -d
docker-compose ps

可以看到已经启动,只有80对外暴露,443没有暴露,然后把上面创建docker-compose.yml增加一行暴露443端口,修改如下:

1
2
3
4
5
6
7
8
version: "3.8"
services:
test-nginx:
container_name: test-nginx
image: test-nginx:latest
ports:
- 8080:80
- 443:443

直接重启docker

1
2
docker restart test-nginx
docker-compose ps

无效,443没有对外暴露

通过docker-compose重启docker

1
2
docker-compose restart
docker-compose ps

同样无效,443没有对外暴露

使用docker-compose关闭再启动

1
2
3
docker-compose down
docker-compose up -d
docker-compose ps

可以看到已经生效,443已经对外暴露

总结

docker-compose配置的参数只有在容器从镜像开始运行时才生效,容器已经存在的情况下(包括运行或停止状态),无法哪些重启操作都不会再加载docker-compose里的配置参数

测试3 修改nginx配置如何生效

通过上面的操作,nginx已经在运行中,我们可以通过8080端口进行正常访问,但因为nginx并没有配置443端口,因此虽然容器已经支持443端口,但nginx还不能识别

直接在容器中修改配置并重启试试

1
2
3
docker exec test-nginx bash -c "sed -i -r '/listen[ ]+80;/a listen  443;' /etc/nginx/conf.d/default.conf"
docker restart test-nginx
docker-compose ps

可以看到能生效

直接在容器中修改配置并使用docker-compose重启

由于上面修改已经生效,需要先删除容器恢复原形,再配置后重启

1
2
3
4
5
6
7
docker-compose down
docker-compose up -d
docker-compose ps

docker exec test-nginx bash -c "sed -i -r '/listen[ ]+80;/a listen 443;' /etc/nginx/conf.d/default.conf"
docker-compose restart
docker-compose ps

也可以正常生效

使用nginx本身的reload

同样先恢复再试

1
2
3
4
5
6
docker-compose down
docker-compose up -d
docker-compose ps

docker exec test-nginx bash -c "sed -i -r '/listen[ ]+80;/a listen 443;' /etc/nginx/conf.d/default.conf"
docker exec test-nginx bash -c "nginx -s reload"

访问也能正常

总结

nginx里的配置无法使用哪种方式重启都是可以正常生效的,主要是因为容器内的进程在容器重启时也会重启。并且通过上面操作可知,直接修改容器里的文件,在容器被删除后再启动后(docker-compose down),就会恢复。因为在容器里的任何操作,如果没有通过挂载永久保存到主机上,容器重新生成后都会丢失。