Docker 指定netcore端口后无效的原因

除夕夜,没回家,在广州敲代码,学习得超级快呀,今天记录一下学习的内容。

我们在使用docker命令行时,在生成docker的container容器时,通常都会指定端口运行,比如:  docker run -it -p 6666:6666 net  imagename

docker端口映射 PORTS docker端口映射后不生效_docker

 

启动后,容器开放的端口与容器内部的kestrel宿主不是相同端口,无法进行端口转发映射,这个时候访问端口外部端口6666是无法访问的。

 

Kestrel原理配置理解

ASP.NET Core项目使用Kestrel作为默认的web服务器。

而集成Kestrel的ASP.NET Core有4中方式指定终结点URL:

  • ASPNETCORE_URLS 环境变量  全局配置法 【这种方案需要频繁得配置生成镜像,使得镜像要一对一对应容器,端口配置只能配置一次,在运行容器时不可变。】
  • --urls命令行参数  【这种方案可以让一个镜像生成多个容器,端口配置多样化。建议
  • urls 主机配置键  【这种方案可以让一个镜像生成多个容器,端口配置多样化。建议
  • UseUrls扩展方法 【这种方案可以让一个镜像生成多个容器,端口配置多样化,但需要配置代码。】
  •  

这段原理配置说明了这个问题有四种处理方案:

 

方案1 : ASPNETCORE_URLS 环境变量 全局配置法 

 

要端口能映射到你对应寄生宿主端口中,则需要配置Dockerfile文件,如下:

ENV ASPNETCORE_URLS=http://+:6666

这句话的意思是说: 把寄生宿主端口设置为6666。

接下来的操作就是:

1.重新生成镜像

#创建 image文件 (-t参数用来指定 image 文件的名字,后面还可以用冒号指定标签 PS:注意最后的 点)
docker build -t aspnetcoredocker1.1 .

2.运行

#生成容器,每运行一次,就会新建一个容器(这里的5000:5000 代表把容器内的5000端口映射到你主机的5000端口,容器端口在后)
docker run -it -p 6666:6666 aspnetcoredocker1.1
#docker run -it -p 6666:6666 aspnetcoredocker1.1:TAG   // 默认TAG是latest

3.查看运行状态

docker ps -a

4.获取站点状态

wget 127.0.0.1:6666

 

5.这种方案的问题总结:

其实这个问题本质上是由于kestrel配置的终结点URL由环境变量Dockfile配置ASPNETCORE_URLS所决定,如果不配置默认为80端口,故每次生成容器后,需要指定一个端口来配置运行。这样的话,就势必会出现一个镜像对应一个容器,那么一个docker 要 运行两个相同项目,就必须要对dockfile进行配置urls,生成镜像并运行启动容器,否则无法映射到外部端口中,这样导致:1个镜像对应一个容器,无法在同一个docker中使用1个镜像多个容器的作法,如果命令行配置 command 来 运行指定 kestrel运行端口,这样话我就不需要每次都去配置dockerfile了。(处理一个镜像可以多个容器运行,并且不用频繁的生成镜像):

方案2. UseUrls扩展方法 :

在net core 代码启动项中使用useurls的参数获取:

docker端口映射 PORTS docker端口映射后不生效_命令行_02

然后在启动docker容器时, 命令加上 对应监听的端口

docker端口映射 PORTS docker端口映射后不生效_docker_03

经过wget后。访问正常

docker端口映射 PORTS docker端口映射后不生效_环境变量_04

 

方案3:urls命令行参数配置方案 和 --url 命令行配置方案 

在命令行中代入 --urls="" 即可监听对应端口 

 

docker端口映射 PORTS docker端口映射后不生效_环境变量_05

 

总结:

一般来说,一台服务器都是一个镜像一个容器的,如果有特殊需求的话,可能一个镜像多个容器,那么就可以用这个方案。

这里需要注意的一点是:

容器虽然是隔离的,但是容器彼此间的端口还是共用的,如果一个容器占用了一个容器内部端口,其他容器是无法占用的。

容器的环境隔离,但容器彼此间使用的硬件,带宽,网络,端口,外部虚拟化的系统都是一样的,不一样的是容器间互相隔离的环境个体。就好像日本酒店以前的共享房间一样。