nginx: [emerg]绑定到0.0.0.0:80失败(98:地址已在使用中)在docker上。

19

我正在尝试获取nginx的默认网页,但在容器运行后无法通过http连接端口80。

我正在运行docker 1.9.9版本。

我所采取的步骤如下:

首先创建了一个Docker文件:

FROM ubuntu:15.10

RUN echo "Europe/London" > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get install -y supervisor
RUN apt-get update && apt-get -q -y install lsof
RUN apt-get install net-tools
RUN apt-get install psmisc
RUN apt-get -y install curl

ADD supervisor.nginx.conf /etc/supervisor.d/nginx.conf

CMD /usr/bin/supervisord -n

RUN rm -Rf /etc/nginx/conf.d/*
RUN rm /etc/nginx/sites-enabled/default

RUN mkdir /etc/nginx/logs/
RUN touch /etc/nginx/logs/error.log

RUN mkdir /usr/share/nginx/logs/
RUN touch /usr/share/nginx/logs/error.log

ADD ./conf/nginx.conf /etc/nginx/sites-available/default
RUN ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

copy ./dist /usr/share/nginx/html

CMD /usr/bin/supervisord -n

Docker文件将下面的nginx配置文件复制到/etc/nginx/sites-available/default,并为/etc/nginx/sites-enabled/default创建了一个符号链接。
server {
  root /usr/share/nginx/html;
  index index.html index.htm;

  # redirect server error pages to the static page /50x.html
  #
  error_page 500 502 503 504 /50x.html;
  location = /50x.html {
    root /usr/share/nginx/html;
  }

  location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
    access_log        off;
    log_not_found     off;
    expires           5d;
  }

  # deny access to . files, for security
  #
  location ~ /\. {
     access_log off;
     log_not_found off;
     deny all;
  }
}

然后我使用以下命令构建了镜像:

docker build -t dnginx 

我使用以下命令启动了容器:

docker run --name d3 -d -p 80:80 dnginx

我找到了IP地址并尝试连接。

curl http://172.17.0.2

涉及技术内容,需要翻译如下:

出现了如下错误信息:

curl: (7) Failed to connect to 172.17.0.2 port 80: Operation timed out

我在容器中打开了bash shell并运行了nginx,结果如下:

nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()

如果我运行netstat --listen,我会得到以下结果:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 *:80                    *:*                     LISTEN

如果我运行netstat -ltnp | grep :80,我会得到以下结果:
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -

我完全不知道正在发生什么。

如果我只连接到nginx镜像,同样的事情也会发生。


我得到:tcp 0 0 *:http : LISTEN - dagda1
这意味着在您的80端口上有某些东西正在监听... - mgaido
lsof -i:80 返回:nginx 1 root 6u IPv4 239214 0t0 TCP *:http (LISTEN)我应该杀掉它吗? - dagda1
1
98:已在使用中意味着有一个正在使用该特定IP/端口地址的进程。您应该了解是哪个进程,可以通过 sudo netstat -ltnp | grep :80 来实现。一旦您了解了它是哪个进程,如果您对它不感兴趣,可以将其终止并重试。 - mgaido
同样的问题,当supervisord被禁用时。 - dagda1
显示剩余3条评论
2个回答

25

这几天我也遇到了同样的问题,但是我必须运行多进程,因此删除supervisord对我来说不是一个解决方案。

只需将-g "daemon off;"标志添加到supervisor nginx程序命令中即可解决问题。也就是说

[program:nginx] command=/usr/sbin/nginx -g "daemon off;"

似乎容器中的所有进程都必须在前台运行,即使由supervisord工具管理。


这是在需要主管时的实际解决方案。谢谢! - Greendrake
2
这个解决方案适用于那些使用supervisord.conf的人。 - KingDarBoja
1
谢谢!我的收获是:当supervisor以守护程序模式(后台)启动nginx时,它会启动并进入后台。现在,supervisor认为nginx已经挂了并试图重新启动它。由于nginx已经在后台运行,它会抱怨端口已经被占用。解决方法是告诉nginx在前台运行,这样supervisor就可以跟踪它(对于仅运行nginx的普通docker映像也是如此)-可以通过CLI选项来完成,如本答案和nginx配置文件中所建议的那样。 - Chirag Ravindra
这对我不起作用,我正在使用supervisord运行命令,我还尝试将nginx端口更改为8080。它仍然显示相同的错误。 - rahulk9

15
我尝试了你的 Dockerfile,结果符合预期。我唯一做出的更改是删除任何涉及 supervisord 的内容,并添加了:
CMD ["nginx", "-g", "daemon off;"]

Dockerfile 的最后。

当容器启动时,它的网络命名空间与主机和其他容器完全隔离,并且唯一存在的进程是由 ENTRIPOINT 或 CMD 指令启动的进程及其子进程,因此我认为您在容器中看到运行的 nginx 进程恰好是由 supervisord 运行的进程。

您确定 172.17.0.2 是 Docker 容器的当前 IP 吗?容器的 IP 不稳定,并且取决于您的主机上运行了多少个容器以及它们启动的顺序。

您使用运行选项“-p 80:80”在主机上公开了 http 端口,所以您应该能够使用 curl 127.0.0.1 访问它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接