【问题标题】:Running a Docker container that accept traffic from the host运行接受来自主机的流量的 Docker 容器
【发布时间】:2015-07-21 07:40:04
【问题描述】:

我有以下配置:
Dockerfile

FROM centos  
MAINTAINER Eduar Tua <eduartua@gmail.com>  

RUN yum -y update && yum clean all
RUN yum -y install httpd && yum clean all
RUN echo "Apache works" >> /var/www/html/index.html

EXPOSE 80

ADD run-apache.sh /run-apache.sh
RUN chmod -v +x /run-apache.sh

CMD ["/run-apache.sh"]

run-apache.sh 脚本:

#!/bin/bash

rm -rf /run/httpd/* /tmp/httpd*

exec /usr/sbin/apachectl -D FOREGROUND

然后我构建图像:

sudo docker build --rm -t platzi/httpd .  

然后

sudo docker run -d -p 80:80 platzi/httpd

之后,当我尝试在 80 端口运行容器接受来自主机的连接时,我得到以下信息:

67ed31b50133adc7c745308058af3a6586a34ca9ac53299d721449dfa4996657
FATA[0002] Error response from daemon: Cannot start container     67ed31b50133adc7c745308058af3a6586a34ca9ac53299d721449dfa4996657: Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use

有什么帮助吗?

【问题讨论】:

  • 您说您正在执行“docker run”,然后在“尝试[ing] 运行容器”之后。为什么你已经运行它之后还要运行它?
  • 嘿@jwodder 这样写是我的错误,运行容器后出现错误。我就是这个意思。
  • 当我检查docker ps 时也没有容器在运行。

标签: apache centos docker dockerfile


【解决方案1】:

错误似乎很明显:

FATA[0002] 来自守护进程的错误响应:无法启动容器 67ed31b50133adc7c745308058af3a6586a34ca9ac53299d721449dfa4996657:启动用户级代理时出错:监听 tcp 0.0.0.0:80:绑定:地址已在使用中

上面写着“地址已在使用中”。这意味着您系统上的某些东西(可能是 Apache 之类的 Web 服务器)已经在侦听端口 80。您需要:

  • 停止网络服务器,
  • -p 参数中为docker run 选择不同的主机端口或
  • 只需删除 -p 参数即可。

由于 Docker 无法设置请求的端口转发,所以没有启动容器。

选项 (a) 和 (b) 都允许容器绑定到主机上的 80 端口。仅当您想从主机以外的其他地方访问容器时才需要这样做。

如果您只想从 docker 主机访问容器但又不想在本地网络上公开容器,则选项 (c) 很有用。在这种情况下,您将使用 docker 分配的容器 IP 地址,您可以通过运行 docker inspect 并仔细阅读输出来获得,或者只是运行:

docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_id

【讨论】:

  • 谢谢@larsks Apache Web 服务器正在我的主机系统上运行。我可以让 Apache 在我的主机上运行并将流量重定向到我的容器吗?都在 80 端口。
  • 你不能让两个东西在同一个 IP 地址的同一个端口上监听。如果您希望您的容器可以从主机外部的 80 端口访问,您需要在主机上分配一个额外的 IP 地址,然后使用 -p 标志 (-p &lt;host_ip&gt;:&lt;host_port&gt;:&lt;container_port&gt;) 将容器绑定到该地址。跨度>
  • 谢谢@larsks,愚蠢的问题。但是你的建议对我帮助很大。
  • 如果这为您解决了问题,请考虑通过单击答案左侧的复选标记将此答案标记为“已接受”。谢谢!
  • 完成@larsks,我是这里的新手。
【解决方案2】:

表示 80 端口正忙...运行此命令查看谁在使用 80 端口

sudo netstat -tlnp | grep 80 # sudo apt-get install net-tools # to install netstat

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1380/nginx -g daemo
tcp6       0      0 :::80                   :::*                    LISTEN      1380/nginx -g daemo

滚动到最右边查看持有端口 80 的进程的违规 PID ...它的 PID 1380 所以让我们做一个进程列表来查看该 pid

ps -eaf | grep 1380

root      1380     1  0 11:33 ?        00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;

所以拆除这个有问题的进程以释放端口 80

sudo kill 1380  # if you know the pid ( 1380 for example )

__ 或 __

sudo fuser -k 80/tcp #  just kill whatever pid is using port 80 tcp

如果在完成上述操作后它仍然说忙,那么您杀死的进程可能会自动重新启动,在这种情况下您需要杀死它的观察者但是您可以从 netstat 输出中向上走进程树以识别这个父进程并杀死它太

这里是如何识别给定进程pid的父pid

ps -eafww

eve         2720    2718  0 07:56 ?        00:00:00 /usr/share/skypeforlinux/skypeforlinux --type=zygote

上面的 pid 是 2720,它的父级将是右侧 pid 2718 的下一列...有命令显示进程树以可视化这些关系

ps -x --forest  

pstree  -p

带有样本输出

systemd(1)─┬─ModemManager(887)─┬─{ModemManager}(902)
           │                   └─{ModemManager}(906)
           ├─NetworkManager(790)─┬─{NetworkManager}(872)
           │                     └─{NetworkManager}(877)
           ├─accounts-daemon(781)─┬─{accounts-daemon}(792)
           │                      └─{accounts-daemon}(878)
           ├─acpid(782)
           ├─avahi-daemon(785)───avahi-daemon(841)
           ├─colord(1471)─┬─{colord}(1472)
           │              └─{colord}(1475)
           ├─containerd(891)─┬─containerd-shim(1836)─┬─registry(1867)─┬─{registry}(1968)
           │                 │                       │                ├─{registry}(1969)
           │                 │                       │                ├─{registry}(1970)

【讨论】:

  • 我已经杀死了使用端口 80 的任何 pid,netstat 显示没有使用端口 80 的 pid,我仍然有同样的问题,我需要检查其他东西吗?
  • @Alaeddine 可能是您杀死的进程自动重新启动,在这种情况下您需要杀死它的观察者,但它会显示在 netstat 上
  • 这不起作用(不再):netstat: option requires an argument -- p
【解决方案3】:

如果您运行的是 Ubuntu,只需运行

sudo /etc/init.d/apache2 stop

然后重新加载你的 Docker 镜像

docker reload

【讨论】:

    【解决方案4】:

    我找到了这样的解决方案:

    $ docker stop container_name
    $ docker commit container_name image_name
    $ docker rm container_name
    

    然后你可以从图像创建一个新容器:

    $ docker run -d -P --name container_name_the_same_or_new image_name
    

    现在可以使用了。

    【讨论】:

      猜你喜欢
      • 2021-03-28
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      • 2022-08-14
      相关资源
      最近更新 更多