运行 一个 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
现在可以使用了。
我有以下配置:
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
现在可以使用了。