thumbnail
Docker+Flask构建后端的踩坑记录

今天第一次尝试用flask构建自己的后端项目,其实一切都挺顺利的。直到部署这个环节,因为我对于Flask和Docker不了解,踩了不少坑。

docker这个东西,对于我这个初学者来说,dockerfile是好文明,但是docker本身不是。

在一开始,我总是尝试pull ubuntu镜像,然后再dockerfile里面写上apt-get install和pip,其实何必呢,完全就有官方的python环境镜像。而且,手动更改系统镜像,不一定能达到效果,就好比今天Python环境搞了半天,发现跑不起来,因为期间的软链接创建不成功,无法执行python app.py这个命令(但是它自带的python3没有问题,但是我要的是python2)

写了个自动搭建dockerfile,仅供参考

//FlaskApp  
//    ├── requirements.txt
//    ├── Dockerfile
//    └── app
//        └── app.py
//        └── <other .py files>
//这是我的目录结构


FROM python:3.7
//直接pull python3.7

MAINTAINER picpo "picpo@foxmail.com"

COPY ./requirements.txt /requirements.txt

WORKDIR /

RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

COPY . /

ENTRYPOINT [ "python" ,"app/app.py" ]

Dockerfile的基本指令有十三个,上面用到了部分;

  • FROM - 所有Dockerfile的第一个指令都必须是 FROM ,用于指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的latest标签,如果需要在一个Dockerfile中构建多个镜像,可以使用多次。

  • MAINTAINER - 描述镜像的创建者,名称和邮箱。

  • RUN - RUN命令是一个常用的命令,执行完成之后会成为一个新的镜像,通常用于运行安装任务从而向映像中添加额外的内容。在这里,我们需更新包,安装 python3pip 。在第二个 RUN 命令中使用 pip 来安装 requirements.txt 文件中的所有包。

  • COPY - 复制本机文件或目录,添加到指定的容器目录, 本例中将 requirements.txt 复制到镜像中。

  • WORKDIR - 为RUN、CMD、ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续参数如果是相对路径,则会基于之前命令指定的路径。

  • ENTRYPOINT - 在启动容器的时候提供一个默认的命令项。

现在 Dockerfile 已经准备好了,而且也了解了Docker的构建过程,接下来为我们的应用程序创建Docker映像:

docker build -t docker-flask:0.1 .

容器化的优点,就是开发的应用程序通过容器部署,从一开始就确保了应用程序构建的环境是干净的,从而消除了交付过程中的意外情况。

但是呢,在开发应用程序的过程中,更重要的是要快速重新构建和测试,以检查验证过程中的每个中间步骤。为此,web应用程序的开发人员需要依赖于Flask等框架提供的自动重启功能(Debug模式下,修改代码自动重启)。而这一功能也可以在容器中使用。

为了启用自动重启,在启动Docker容器时将主机中的开发目录映射到容器中的app目录。这样Flask就可以监听主机中的文件变化(通过映射)来发现代码更改,并在检测到更改时自动重启应用程序。

此外,还需要将应用程序的端口从容器转发到主机。这是为了能够让主机上的浏览器访问应用程序。

因此,启动Dokcer容器时需要使用 volume-mappingport-forwarding 选项:

docker run --name flask_app -v $PWD/app:/app -p 1000:5000 docker-flask:0.1

该命令将会执行以下操作:

  • 基于之前构建的 docker-flask 镜像启动一个容器;

  • 这个容器的名称被设置为 flask_app 。如果没有 ——name 选项,Docker将为容器生成一个名称。显式指定名称可以帮助我们定位容器(用来停止等操作);

  • -v 选项将主机的app目录挂载到容器;

  • -p 选项将容器的端口映射到主机。

现在可以通过http://localhost:5000 或者 http://0.0.0.0:5000/ 访问到应用

然而,然而,第二个坑就是我今天对Flask掌握不足的问题了(,在成功做好端口映射后,我在宿主机环境一直一直curl localhost:10000失败,返回的字符是curl: (52) Empty reply from server。很难绷得住,因为这端口好像转发成功了,但是啥也没有,其他的没有服务的端口都是refuse,压根没开,所以这是咋回事呢?我百思不得其解。

终于找到了一篇讲Flask的博客(https://blog.csdn.net/qq_26591517/article/details/86423838),里面有这么提到:

“用python开启flask web服务时:(1)你只需要本机访问,那ip只要不设置为0.0.0.0就可以,正常访问就好。(2)如果你需要外网访问,ip需要设置为0.0.0.0,此时,在本机上访问需要使用默认的127.0.0.1(也就是你不设置ip时默认的ip),在外网上访问则需要使用你本机的ip,不要使用0.0.0.0”

原来如此,我立马把

if __name__ == "__main__":
    app.run()

改为:

if __name__ == "__main__":
    app.run(host="0.0.0.0")

成功了!

上一篇
下一篇