这几天考虑着要把猪比移到一个docker容器里跑,以免开放上传插件后有使用Python沙箱逃逸炸服的。
于是我简单学习了一下docker的基本知识。之前虽然用过docker,但大多都是直接复制的安装容器的指令,其实并不理解。

经过简单的学习之后,我开始创建一个新的容器。

Step: 1 Python镜像

由于猪比基本是由Python编写的,我选择基于Python创建容器。
先用docker pull python:3.8下载python,指定python版本为3.8。

Step: 2 创建容器

使用docker run创建容器。
首先明晰该指令的用法:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

IMAGE

那么我们首先要考虑的就是image镜像。这里不用考虑,直接用刚刚的python:3.8。

OPTIONS

  • -p
    猪比需要在8000端口使用flask创建服务器,所以这里我们要使用-p参数指定端口映射。格式为:-p 宿主机端口:容器端口
    由于都是使用8000端口,所以这里我们使用-p 8000:8000即可
  • -v
    使用-v来设置一个目录映射。由于我需要随时修猪比的bug,而不可能每改完一次就docker cp一次,所以这里就非常有必要添加一个目录映射。
    格式为:-v 宿主机地址:容器内地址
    我是用的就是-v /www/gch/python:/pbf
  • --name
    用这个选项来指定容器名。如果不指定容器名,我们就需要使用分配的容器ID来操作容器。这样的话打起字来也非常麻烦。
    格式:--name 容器名
    我使用的是--name pbf
  • -d
    后台运行容器,并返回容器ID

Step: 3 bug解决

寻找问题

终于创建完容器了,我兴高采烈的在宿主机用curl试了一下8000端口。但是curl告诉我8000端口无法连接。我当时愣住了,又用telnet试还是不行。于是docker exec -it pbf /bin/bash进入容器的终端,在容器内部curl8000端口发现可以正常访问。那么问题就很明显了:就是端口映射的问题。

解决方案

  • firewalld
    当即想到了是不是firewalld在搞鬼。但是看了看firewalld的端口,发现8000端口已经放行了。不甘心,systemctl stop firewalld关掉防火墙。但是没啥卵用还是不行。
  • ip_forward
    我又google了一大堆,看到了另一个原因:ip转发
    关于IP转发这里不过多赘述,使用cat /proc/sys/net/ipv4/ip_forward查看了一下发现为1。证明我的IP转发是开着的。
    再搜,网上就只有firewalldip_forward这两种说法了。
  • 网段占用
    百思不得其解。正当这时,看到了一篇文章:解决Docker端口映射
    按照说的试了试,发现容器内雀氏无法请求外网。但是奇怪的是我的服务器并不是阿里云的,ifconfig发现也没有网段占用。
    不过我还是抱着试试的心态改了一下Docker的网段。然后就发现容器内可以请求外网了。不过端口问题还是没有解决。
  • 最终解决
    最后,我去Docker hub上看了看那个著名的flaskapp。既然他都可以成功端口映射,那为啥我不行?
    最终发现:app.run的时候指定的host不能是127.0.0.1,而是0.0.0.0。改了,运行,完美解决!
    其实是因为0.0.0.0意思是监听网卡所有地址,所以以后开服务器的时候尽量不要用127.0.0.1了,使用0.0.0.0

总结

经过这近一整个下午的折腾,总算是基本把Docker搞明白了。同时困扰和耗时最多的问题就是端口映射的问题。这个经历也告诉我们:遇到问题时要多看看实例,看看别人是怎么写的,与自己写的有啥不同,这个不同会造成什么影响?