背景
由于项目采用的是镜像以host网络模式部署,默认暴露端口是80,显然80端口很容易被占用,即便 默认暴露一个不容易被占用的端口也不是最终办法,限制了镜像拿到任意机器上部署,因此我们需要在容器启动的时候指定想要暴露的端口。
解决
解决思路很简单,就是通过 docker run 的时候将想要暴露的端口传递进容器,然后修改nginx默认监听端口。传递方式有一下两种。
- 方式一:通过 docker run -e 的方式指定环境变量,容器内部再去处理这个环境变量(推荐)
- 方式二:在 docker run 的最后追加参数,容器内部去获取该参数,并处理。(eg:docker run -it --name myNginx -d nginx expose_port=xxx),采用这种方式的话,Dockerfile中必须用 ENTRYPOINT 。
我们采用的方式一,通过 docker run -e EXPOSEPORT=XXX 就可以将自定义端口传递进去,通过脚本替换掉nginc.conf中监听的端口。Dockerfile 文件添加一下内容即可。
# 设置环境变量 EXPOSEPORT 默认值为 88,后面可以通过docker run -e EXPOSEPORT="XXX"修改,这个环境变量在容器里也可以$EXPOSEPORT获取
ENV EXPOSEPORT 88
# 暂定默认88
EXPOSE $EXPOSEPORT
# 不能用[]这种形式,否则读取不到环境变量
ENTRYPOINT sh /root/image_run.sh $EXPOSEPORT
这里需要注意的点就是 ENTRYPOINT 后面不可以跟[“sh”, “/root/image_run.sh”, $EXPOSEPORT] ,因为[]这种模式就不会是 shell 方式了,读不到变量的值。
下面在记录一下 Dockerfile 中 EXPOSE 暴露端口的作用:
结论:
Dockerfile 中的 EXPOSE用处不大!主要是为了规范,方便其他人员理解。
原因:
EXPOSE 的官方用途:
- 在Dockerfile中声明了哪些端口是将要开放的。
- 在构建容器时通过 -P (大写的P)可以随机映射端口。(如果EXPOSE没有指定端口,那么使用 -P 参数无效)
为什么说它用不不大呢?
- 真正的暴露端口是在创建容器 run 的时候指定的 -p 或者 -P 参数,先来说说 -p 参数后面跟的是【主机端口:容器端口】,既然在运行的时候还需要指定端口那么 EXPOSE还有什么用呢!
- 当我们创建容器 run 的时候指定参数是 -P,那么在运行之后 会把 EXPOSE 的端口随机映射到主机的不同端口,既然映射到不同的端口那么容器的端口就是是随机的不确定的,那就要在运行之后才能知道端口,这样使用起来是极其不便的。