运行 一个 Docker 接受来自主机的流量的容器

Running a Docker container that accept traffic from the host

我有以下配置:
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"]

运行-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

有什么帮助吗?

错误似乎很清楚:

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

它说,"address already in use"。这意味着您系统上的某些东西——可能是像 Apache 这样的 Web 服务器——已经在侦听端口 80。您将需要:

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

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

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

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

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

说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)

如果你运行宁Ubuntu,只是运行

sudo /etc/init.d/apache2 stop

然后重新加载您的 Docker 图片

docker reload

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

$ 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

现在可以使用了。