Server 7 ,Docker Nginx实战,端口映射问题( 解决端口映射冲突与配置难题 )

发布于:2025-03-12 ⋅ 阅读:(46) ⋅ 点赞:(0)

目录

引言
一、环境说明
二、问题描述
三、解决方案
3.0 端口详细说明
3.1 检查端口占用情况 
① 确认服务端口
② 停止移除占用
3.2 停止移除容器
① 停止移除容器
② 运行新的容器
3.3 处理命名冲突
3.4 启动新的Nginx容器
① 启动容器
② 注意事项
③ 映射其它
3.5 验证服务是否正常工作
四、命令总结
五、本文总结

前言

在现代Web开发中,Docker已经成为部署应用的标准工具之一。它提供了便捷的环境隔离和快速部署的能力,使得开发者能够更加专注于代码本身,而不是服务器配置。这里将围绕如何在Docker环境中部署Nginx服务展开讨论,并详细讲解如何解决遇到的端口映射冲突、配置文件挂载等问题。

一、环境说明

  • 操作系统:Linux Ubuntu( 乌班图 )
  • Docker版本:最新稳定版
  • Nginx配置文件位置:/usr/local/develop/docker-app/nginx/conf/nginx.conf
  • 网站根目录位置:/usr/local/develop/docker-app/nginx/html/xz_control
  • nginx.conf 配置文件
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    #include /etc/nginx/conf.d/*.conf;

    server {
    	listen       80;       # 配置监听的端口
    	listen  [::]:80;
    	server_name  localhost;    # 配置的域名
      
    	# system one
    	location / {
    		root   /usr/share/nginx/html/xitong;  # 网站根目录
    		index  index.html index.htm;   # 默认首页文件
    		# 前端加载404问题
    		try_files $uri $uri/ /index.html;
    	}
    	
    	location ^~/prod-api/{
    		proxy_pass http://192.168.110.40:9012/;
    	}
    	location ^~/prodpy-api/{
    		proxy_pass http://192.168.0.43:7777/;
    	}
    }

    server {
    	listen       81;       # 配置监听的端口
    	listen  [::]:81;
    	server_name  localhost;    # 配置的域名
      
    	# system two
    	location / {
    		root   /usr/share/nginx/html/xz_control;  # 网站根目录
    		index  index.html index.htm;   # 默认首页文件
    		# 前端加载404问题
    		try_files $uri $uri/ /index.html;
    	}
    	
    	location ^~/prod-api/{
    		proxy_pass http://192.168.110.40:9011/;
    	}
    	location ^~/prodpy-api/{
    		proxy_pass http://192.168.0.43:7777/;
    	}
    }
    
}

这里的nginx.conf文件,配置了两个server块,分别监听80和81端口。在Docker容器中运行这个配置,并正确地映射主机的端口到容器内的相应端口时,遇到问题。


二、问题描述

在尝试通过Docker运行Nginx服务时,遇到了端口81 已经被其他服务占用的问题,同时发现名为nginx-new的容器名称已被使用,导致无法直接启动新的容器。


三、解决方案

3.0 端口详细说明

        端口就像是家里不同房间的门牌号,每个门牌号对应着家里不同的房间。在计算机的世界里,端口就是这样一个概念,它帮助电脑区分不同应用程序或服务的“房间”。总共有65536个这样的“房间”,从0到65535编号。

        其中一些“房间”有特别的用途,比如HTTP(超文本传输协议)使用80号端口,这是当你访问一个网站时,默认用来传输网页内容的通道;而HTTPS(安全的超文本传输协议),用于加密和安全地浏览网页,则默认使用443号端口。通过这些特定的端口号,电脑能够准确无误地把数据送到正确的应用程序手中,就像邮递员根据地址把包裹送到正确的家门口一样。这样,无论你是浏览网页、发送邮件还是进行在线聊天,都能顺利进行而不发生混乱。

3.1 检查端口占用情况 

① 确认服务端口

首先,我们需要确认哪些服务正在使用81端口

查找占用80端口的进程:

sudo lsof -i :80

查找占用81端口的进程:

sudo lsof -i :81

实际执行和响应(执行成功):

xingdun@xingdun-ThinkStation-P330:~$ sudo lsof -i :81

COMMAND      PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 127483 root    4u  IPv4 739301      0t0  TCP *:81 (LISTEN)
docker-pr 127491 root    4u  IPv6 742405      0t0  TCP *:81 (LISTEN)

从这里的输出可以看到,端口81已经被一个Docker进程(docker-pr)占用。具体来说,PID为127483和127491的进程正在监听81端口。这意味着您需要停止相关的容器以释放81端口,或者选择将新容器的端口映射到主机上的其他未被占用的端口。

② 停止移除占用

这里来停止并移除占用81端口的容器 

首先,需要找出哪个容器正在使用这些端口。该命令会列出所有发布(即映射)了81端口的容器:

docker ps --filter "publish=81"

实际执行和响应(执行成功):

xingdun@xingdun-ThinkStation-P330:~$ docker ps --filter "publish=81"

CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS                                       NAMES
69b39f5df9a5   nginx     "/docker-entrypoint.…"   20 minutes ago   Up 20 minutes   80/tcp, 0.0.0.0:81->81/tcp, :::81->81/tcp   my-nginx

根据响应信息,有一个名为 my-nginx 的容器正在使用81端口。

这里并没有直接的矛盾或额外的冲突。lsof 输出中的 docker-pr 进程是 Docker 内部用于处理端口映射的进程,它们与 docker ps 显示的 my-nginx 容器直接相关。也就是说,正是 my-nginx 容器通过 Docker 的端口映射机制占用了主机的81端口,而 docker-pr 是实现这一映射的进程。

3.2 停止移除容器

停止并移除现有的 my-nginx 容器

如果您不再需要现有的 my-nginx 容器,可以先停止并移除它以释放81端口。

① 停止移除容器

停止并移除现有的 my-nginx 容器

该命令,用于停止一个正在运行的容器,这里表示它将会停止名为  my-nginx 的容器:

docker stop my-nginx

该命令,用于移除一个已经停止的容器,这里表示它将会移除名为 my-nginx 的容器:

docker rm my-nginx
② 运行新的容器

运行新的 nginx-new 容器

docker run --name nginx-new \
-v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /usr/local/develop/docker-app/nginx/html/xitong:/usr/share/nginx/html/xitong:ro \
-v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro \
-p 80:80 -p 81:81 \
-d nginx

各参数的作用

  • docker run: 运行一个新的容器。
  • --name nginx-new: 给容器命名为 nginx-new。这使得你可以通过这个名字来引用这个容器,而不是使用其ID。
  • -v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro: 将主机上的 /usr/local/develop/docker-app/nginx/conf/nginx.conf 文件挂载到容器内的 /etc/nginx/nginx.conf 路径下,且以只读模式 (ro) 挂载。这意味着容器会使用你指定的Nginx配置文件而不是默认的配置文件。
  • -v /usr/local/develop/docker-app/nginx/html/xitong:/usr/share/nginx/html/xitong:ro: 将主机上的 /usr/local/develop/docker-app/nginx/html/xitong 目录挂载到容器内的 /usr/share/nginx/html/xitong 路径下,同样以只读模式挂载。这样做的目的是让Nginx能够访问你的网站根目录下的内容。
  • -v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro: 类似地,将另一个网站根目录挂载到容器内相应的路径下。
  • -p 80:80: 将主机的80端口映射到容器内的80端口。这意味着任何发送到主机80端口的请求都会被转发到容器内的80端口上运行的服务(在这个例子中是Nginx)。
  • -p 81:81: 同样地,将主机的81端口映射到容器内的81端口,允许外部访问容器内监听在81端口上的服务。
  • -d nginx: 使用官方的 nginx 镜像以后台模式 (detached mode, 简写为 -d) 启动容器。

这条命令的主要功能包括:

  1. 创建并命名一个新容器 (nginx-new)。
  2. 挂载自定义的Nginx配置文件 到容器内部,覆盖默认配置。
  3. 挂载两个不同的网站根目录 到容器内部,以便Nginx可以提供这些网站的内容。
  4. 设置端口映射,使得可以通过主机的80和81端口访问容器内的Nginx服务。
  5. 以后台模式启动容器 使用官方的 Nginx 镜像。

通过这种方式,可以利用Docker容器技术,来部署具有特定配置的Nginx服务器,并且可以方便地管理和扩展这种部署方式。

实际执行和响应(执行报错):

xingdun@xingdun-ThinkStation-P330:~$ docker run --name nginx-new \
-v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /usr/local/develop/docker-app/nginx/html/xitong:/usr/share/nginx/html/xitong:ro \
-v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro \
-p 80:80 -p 81:81 \
-d nginx


docker: Error response from daemon: Conflict. The container name "/nginx-new" is already in use by container "6f3f3841caae693acf44de52904ee14dcaa6e9e17e0f0b2c37023e3198d9ac49". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.

从错误信息来看,名为 nginx-new 的容器名称已经被占用。这意味着之前有一个名为 nginx-new 的容器已经存在,即使它可能没有成功启动或者已经被停止了。您需要先处理这个现有的容器,才能使用相同的名字来运行新的容器。

3.3 处理命名冲突

由于存在名为nginx-new的容器,我们需要先停止移除现有的同名容器。

该命令,用于停止一个正在运行的容器,这里表示它将会停止名为 nginx-new 的容器:

docker stop nginx-new

该命令,用于移除一个已经停止的容器,这里表示它将会移除名为 nginx-new 的容器:

docker rm nginx-new

3.4 启动新的Nginx容器

① 启动容器

接下来,我们可以使用以下命令,来启动一个新的Nginx容器,并正确地挂载配置文件和网站根目录,同时进行端口映射:

docker run --name nginx-new \

-v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \

-v /usr/local/develop/docker-app/nginx/html/xitong:/usr/share/nginx/html/xitong:ro \

-v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro \

-p 80:80 -p 81:81 \

-d ngin

实际执行和响应(执行成功):

xingdun@xingdun-ThinkStation-P330:~$ docker run --name nginx-new \

-v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \

-v /usr/local/develop/docker-app/nginx/html/xitong:/usr/share/nginx/html/xitong:ro \

-v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro \

-p 80:80 -p 81:81 \

-d nginx

844f3be41d4d26dcb188e87ca85a4c184a2b83621313f16bb2e381c500c28

这里表示已经成功地运行了新的 Docker 容器 nginx-new,并且没有出现错误信息。Docker 返回了一个容器 ID (844f3be41d4d26dcb188e87ca85a4c184a41a84e5a2b836f16bb2e381c500c28),这表明容器已经被正确创建并以后台模式启动。

② 注意事项
  • -v 参数用于挂载主机上的文件或目录到容器内,ro 表示只读模式。
  • -p 参数用于端口映射,确保外部可以访问容器内的服务。
  • -d 参数表示以后台模式运行容器。
③ 映射其它

还可以选择将新容器的81端口映射到主机上的其他未被占用的端口,例如8081:

docker run --name nginx-new \
-v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /usr/local/develop/docker-app/nginx/html/xitong:/usr/share/nginx/html/xitong:ro \
-v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro \
-p 80:80 -p 8081:81 \
-d nginx

3.5 验证服务是否正常工作

在执行 docker run 命令后,Docker 会基于 Nginx 镜像创建并启动一个新的容器,并且该容器会自动运行 Nginx 服务。由于 -d 参数的作用,这个容器会在后台运行。因此,在正常情况下,执行完这条命令后不需要手动重启 Nginx。启动容器后,可以通过浏览器输入 IP + 81 端口进行访问​:192.168.xxx.40:81​前端系统页面。

不过,有几种情况可能需要重新加载或重启 Nginx:

① 配置文件更新

如果您修改了挂载到容器内的 Nginx 配置文件(例如 /usr/local/develop/docker-app/nginx/conf/nginx.conf),则需要让 Nginx 重新加载配置。可以通过以下命令进入正在运行的容器,并发送重载信号:

docker exec nginx-new nginx -s reload

这条命令会让 Nginx 重新加载配置文件而不停止服务

运行结果如果是[notice] 42#42: signal process started:这是 Nginx 日志中的一个通知消息,表示它已经收到重新加载信号,并且已经开始处理该请求。这里的 42#42 指的是进程ID和工作进程ID,表明哪个进程正在处理此操作。

② Nginx 容器停止或异常退出

如果容器内的 Nginx 服务因某种原因停止了,您可以重启整个

docker restart nginx-new

这将重启容器及其内部的所有服务,包括 Nginx。

③ 验证 Nginx 是否正常工作

如果您想检查 Nginx 是否正确地启动并且没有遇到任何错误,可以查看容器的日志:

docker logs nginx-new

如果发现有任何错误信息,根据错误提示进行相应的修正可能是必要的。

注意这里的nginx-new是容器名称。


四、命令总结

为了便于理解和应用每条命令的作用,这里来总结并排序

1. 查看端口占用情况

sudo lsof -i :81

查看81端口使用情况。

2. 列出占用指定端口的容器

docker ps --filter "publish=81"

查找使用81端口的容器。

3. 停止指定容器

docker stop my-nginx

停止名为my-nginx的容器。

4. 移除指定容器

docker rm my-nginx

删除名为my-nginx的容器。

5. 运行新的Nginx容器

docker run --name nginx-new \
-v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro \
-p 81:81 \
-d nginx

启动新Nginx容器并映射端口。

6. 运行新容器并映射到不同端口

docker run --name nginx-new \
-v /usr/local/develop/docker-app/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /usr/local/develop/docker-app/nginx/html/xz_control:/usr/share/nginx/html/xz_control:ro \
-p 8081:81 \
-d nginx

映射至未占用端口(如8081)。

7. Nginx 容器停止或异常退出

docker restart nginx-new

重启容器及其内部的所有服务。

8. 重新加载 Nginx 配置

docker exec nginx-new nginx -s reload

重新加载Nginx配置文件,只针对 Nginx。

这些命令覆盖了从检查端口占用、管理Docker容器、到调试和维护Nginx服务的全过程。希望对你有所帮助!


五、本文总结

通过上述步骤,我们成功解决了Docker中部署Nginx服务时遇到的端口映射冲突问题。同时,我们也学会了,如何正确挂载配置文件和网站根目录,确保服务按照预期运行。希望这里能帮助到同样面临这些问题的你。如果有任何疑问或需要进一步的帮助,请随时留言交流!