本文写给没有部署经验的小伙伴们,网上文章很多,但是照着网上的例子,有可能会遇到些问题,但切记不要着急,跟着错误提示,慢慢百度,总能找到你要的答案,你的问题一定不是个例。

先谈一下总体步骤:

预先准备:在Linux服务器上安装Docker;

先查看操作系统版本:cat /proc/version,比如:Ubuntu等;

然后参考菜鸟教程安装对应版本的docker(通过这个网站要熟悉常用的docker知识),这一步一般不会出问题,安装完成后执行以下命令:

sudo docker run hello-world,如果运行成功会出现Hello from Docker! This message shows……

下面正式开始部署相关:

主要步骤命令及说明如下:

1、mkdir docker_flask
2、sudo vim app_flask.py
添加以下代码:

from flask import Flask
app = Flask(__name__)
@app.route('/')
 def hello_world():
     return 'Hello World!'if __name__ == '__main__':
     app.run(debug=True)

使用命令:wq退出保存,vim 没有可以自行安装,建议安装,使用方便

3、安装依赖:主要是requirements.txt
执行命令:pip freeze > requirements.txt,也可以手动添加,
此处有个包可以安装下:pip install pipreqs
,进入需要生成文件的目录执行: pipreqs ./ ,用dir 查看可以看到已经生成文件

4、编写gunicorn(绿色独角兽)配置文件gunicorn.conf.py文件
sudo vim gunicorn.conf.py
 
添加一下代码:

workers = 5
 worker_class = "gevent"
 bind = "0.0.0.0:8080"5、执行python app_flask.py,如果成功可以用浏览器访问:http://127.0.0.1:5000/,可以看到hello world!
6、最关键的一步,我也会做详细的说明
 sudo vim Dockerfile
 添加以下内容:
 FROM python:3
 MAINTAINER WuJian_Home
 COPY requirements.txt ./
 RUN pip install --no-cache-dir -r requirements.txt
 COPY . .
 CMD ["gunicorn", "app_flask:app", "-c", "./gunicorn.conf.py"] 以下不用添加
 解释一下参数:
 FROM   # 指明你创建的镜像,他的基础镜像是谁,说白了就是安装后面的环境python,并指定版本3,也可以指定其他版本,比如:python:3.6
 MAINTAINER  # 维护者信息, 添上自己的信息,这里还是用原作者的吧
 COPY  # 将宿主机的文件cp到创建的镜像当前路径下,这种./ .啥的,刚开始接触,可能有点陌生,习惯就好了,就类似windows的目录层级
 RUN  # 你需要在创建镜像之前,需要执行的命令,就是安装所需的所有依赖包,比如我需要numpy、pandas等一行放一个就可以,也可以指定版本号,这个requirements.txt文件可以自动添加,也可以手动输入
 CMD  # 创建容器后执行的第一个命令,这个写法可能对初学者看的一脸懵逼,什么玩意,其实就是在容器启动后执行的一行命令:翻译下这个命令,相当于在容器启动后执行,gunicorn app_flask:app -c ./gunicorn.conf.py,这是绿色独角兽的一条命令,详细可以了解下绿色独角兽的基本使用:gunicorn,当然执行这个命令往往会出些问题,不过当前你发现不了,因为还没执行,接下来会介绍。7、制作docker image
 我这里镜像的名字直接做成flask_demo了,注意后面有个点docker build -t flask_demo:1.0 .
制作完成了,可以看到还是蛮大的,接下来就是使用它了
docker image ls -a | grep flask_demo
 docker images | grep flask_demo两个命令一样,喜欢用哪一个看你自己啊
8、使用这个镜像创建容器(如果对容器和镜像不太熟悉,可以先看看docker的基本知识)
 docker run -it --name=flask_app -p 5001:8080 flask_demo:1.0
解释一下参数
 --name   # 是给你创建的容器起一个名字,在后续进行容器操作的时候可以直接使用名字,不用在使用id
 -p   # 将宿主机的端口映射到容器中,8080是必须的,上面指定了,前面的端口可以自己定义,后面用浏览器访问时要用到如果没有报错,出现:
 strarting gunicorn 19.9.0
 Listening at: http://0.0.0.0:8080
 .....
  测试是否构建成功:在宿主机(就是你本地的机器)用浏览器访问:http://127.0.0.1:5000/(注意:不是这个地址http://0.0.0.0:8080),可以看到hello world!
按ctrl退出,再次启动,可以使用命令:docker container start flask_app,其中flask_app是容器的名字,刚才docker run时指定的
恭喜,不但成功构建了镜像,也构建了容器,服务成功启动,
 如果想后台启动,在命令中加 -d
 docker run -it -d --name=flask_app -p 5001:8080 flask_demo:1.0
 此时不会再出现这一堆(strarting gunicorn 19.9.0
 Listening at: http://0.0.0.0:8080


.....),而是会出现一串id,表明容器构建且启动成功了,并在容器中立即执行了gunicorn app_flask:app -c ./gunicorn.conf.py,一定要分清你的宿主机中,还是在容器中,CMD命令是容器启动后在容器中执行的命令。

9、后面可以发布你的镜像,用的时候再拉取。

如果你按照上面的操作,执行没有任何报错,恭喜你,你是幸运的,好多帖子也是你超我我超你,但是其实后面会遇到很多问题。我们一一总结下常见的问题。

主要问题归纳:

实际过程中,肯定会出现各种各样问题,对Linux及docker初学者来说有点懵逼,不要担心,根据错误提示,一般都能找到答案。

问题1:pip install - r requirement.txt时速度太慢怎么办或者出现没有该版本的包

更换源比如可以写作:pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/


创建或修改 /etc/docker/daemon.json 文件,修改为如下形式

vi /etc/docker/daemon.json
 {
 "registry-mirrors": ["http://hub-mirror.c.163.com"]
 }
 systemctl restart docker.service

问题2:requirement.txt如何自动生成依赖

主要参考:

pip install pipreqs

进入需要生成文件的目录执行: pipreqs ./

问题3:如何在进入容器后安装包,并且有时候会报bash: vi: command not found
E: Unable to locate package vim类似错误怎么办

首先在容器中(注意再强调遍,在容器中),执行apt-get update
然后执行:apt-get install vim

问题4:执行到CMD ["gunicorn", "app_flask:app", "-c", "./gunicorn.conf.py"]报错,比如在docker run 时进入容器中执行命令时出现这个错误,Python3.10 ImportError: cannot import name ‘Mapping‘ from ‘collections‘ (/usr/local/lib/python3.10

主要原因就是因为既安装了Python 2.7又安装了Python3.6等版本导致冲突,两种方法:

第一:在容器中根据错误提示目录位置(一般哪句错误都是提示绝对路径,在容器中找到即可),找到from_dict.py文件,修改为"from collections import Mapping" 改为"from collections.abc import Mapping"

第二:可以卸载Python2.7,重新安装Python3.6等版本,即可解决

主要参考:


补充:linux环境下如何卸载软件,

卸载:python3.4
sudo apt-get remove python3.4
或者用该命令清除python3.4,sudo apt-get purge --auto-remove python3.4

问题5:docker可以不用每次输入sudo,加入用户组即可

创建一个docker组

$ sudo groupadd docker
添加当前用户到docker组
    $ sudo usermod -aG docker $USER
     //sudo usermod -aG docker yundong登出,重新登录shell
$ sudo service docker restart

问题6:OSError: [Errno 98] Address already in use,端口号占用,需要杀死原端口号,或是更滑端口,使用终端命令杀死进程
先查找进程id,使用命令  lsof -i:端口号 ,比如:lsof -i:5050  , 可通过端口号来查找进程ID
然后执行:kill -9 pid