话说去年年底给另外一个组的同事写了一个简单的工单查询系统,用flask写的,当时是部署在我们组的一台测试物理机上,操作系统是Redhat 7。后来我们组的这台测试物理机要做其它用途,领导给两天时间让把应用迁走,问了使用这个应用的同事,他们组自己有一台测试机,可以部署到他们自己的测试机上,于是又搞一通部署。最近使用这个应用的同事又跑过来找我,说他们那台测试机要重装系统,有其它用途。彻底无语,忍无可忍了,用docker吧!搞完之后总结一下,记个笔记。
准备环境
Linux OS
[root@labhost ~]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
Docker Engine
Docker安装请参考官网:https://docs.docker.com/engine/install/centos/#install-using-the-repository
[root@labhost pyalpine]# docker version
Client: Docker Engine - Community
Version: 19.03.12
API version: 1.40
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:46:54 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.12
API version: 1.40 (minimum version 1.12)
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:45:28 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
环境准备好之后开搞
#创建项目文件夹
[root@labhost ~]# mkdir pyalpine
#进入项目文件夹
[root@labhost ~]# cd pyalpine
#创建requirements.txt,实际项目开发中是直接用pip freeze直接生成,这里为了方便是手动创建的,而且这里面我只放了Flask,实际项目会有很多依赖包。
[root@labhost pyalpine]# vim requirements.txt
[root@labhost pyalpine]# cat requirements.txt
Flask>=1.1.1,<1.2
#创建app.py文件
[root@labhost pyalpine]# vim app.py
#代码如下:
[root@labhost pyalpine]# cat app.py
from flask import Flask
app = Flask(__name__)
@app.route(‘/‘)
def hello_world():
return ‘Hello, Flask which is running on Docker container!‘
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port="5000")
#接下来我们创建Dockerfile,注意:Dockerfile的首字母是大写!!!
[root@labhost pyalpine]# vim Dockerfile
Dockerfile内容如下:
[root@labhost pyalpine]# cat Dockerfile
#拉取镜像
FROM python:3.7-alpine
#指定工作目录,目录名称自己定义,如果当前指定的目录不存在的话,这个目录会自动被创建
WORKDIR /demoapp
#复制当前文件夹下的所有项目文件到docker的工作目录,也就是我们上面指定的目录
COPY ./ ./
#根据requirements.txt文件,安装相关依赖包
RUN pip install -r requirements.txt
#指定docker运行的时候默认执行的命令,我们想让flask网站随docker启动时就运行
CMD ["python", "app.py"]
接下来我们来构建我们自己的docker image:(注意不要把点号给遗漏了!-t参数指定tag,也就是你的docker image叫什么名字)
[root@labhost pyalpine]# docker build . -t mypyalpine
Sending build context to Docker daemon 4.096kB
Step 1/5 : FROM python:3.7-alpine
---> 6ca3e0b1ab69
Step 2/5 : WORKDIR /demoapp
---> Using cache
---> c89343983176
Step 3/5 : COPY ./ ./
---> 2cb8fce548c8
Step 4/5 : RUN pip install -r requirements.txt
---> Running in 00911a463614
Collecting Flask<1.2,>=1.1.1
Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting itsdangerous>=0.24
Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2>=2.10.1
Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting click>=5.1
Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Werkzeug>=0.15
Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting MarkupSafe>=0.23
Downloading MarkupSafe-1.1.1.tar.gz (19 kB)
Building wheels for collected packages: MarkupSafe
Building wheel for MarkupSafe (setup.py): started
Building wheel for MarkupSafe (setup.py): finished with status ‘done‘
Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-py3-none-any.whl size=12629 sha256=f9ec10f37be2db2c6a39211640b9b8336c7be48743dd4a91d13db0ea5e8fe727
Stored in directory: /root/.cache/pip/wheels/b9/d9/ae/63bf9056b0a22b13ade9f6b9e08187c1bb71c47ef21a8c9924
Successfully built MarkupSafe
Installing collected packages: itsdangerous, MarkupSafe, Jinja2, click, Werkzeug, Flask
Successfully installed Flask-1.1.2 Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 itsdangerous-1.1.0
Removing intermediate container 00911a463614
---> 12e21da37c96
Step 5/5 : CMD [‘python‘, ‘app.py‘]
---> Running in ad78a874fd79
Removing intermediate container ad78a874fd79
---> f0d4b0160413
Successfully built f0d4b0160413
Successfully tagged mypyalpine:latest
恭喜你,你已经成功构建了一个自己的docker image:mypyalpine,那我们现在来让他跑起来:
[root@labhost ~]# docker run -p 5050:5000 --name myflask mypyalpine
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 236-169-898
简单介绍一下:
docker run:想要跑一个docker,必须要敲的命令
-p 5050:5000:指定端口映射,冒号前面的是暴露到外面的端口号,冒号后面的是在docker里面的端口号
--name myflask:指定将要跑起来的docker的名称,可选参考,但是推荐加上,否则docker服务会自己随机给你的docker起个名字,你都不认识,所以自己的孩子还是起个好听点的名字,方便自己记忆和使用。
mypyalpine:这个是上一步我们构建docker image时,给image起的名字,这个必须指定,别指定错了。
小伙伴发现了没有,上面我们运行docker之后,终端直接显示的我们的flask程序启动的信息,没办法再输入其它命令了,如果你想继续输入指令怎么搞?所以上面运行docker的命令格式不是太好,我们再来改造一下,让我们的docker启动之后在后台运行,只需加上一个 -d参数即可,然后我们再用docker ps来查看正在运行的container信息:
[root@labhost pyalpine]# docker run -d -p 5050:5000 --name myflask mypyalpine
d464fd0fa04893db4640cc3f2afe201ca07718978bc55f7a17bcc909cab25475
[root@labhost pyalpine]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d464fd0fa048 mypyalpine "python app.py" 3 seconds ago Up 2 seconds 0.0.0.0:5050->5000/tcp myflask
[root@labhost pyalpine]#
注意:如果你第一次运行docker run没有加 -d参数,想再次运行docker run加-d参数,是会报错的,此时你需要先停止当前运行的container,然后删除container,最后再运行加上 -d参数的命令就可以了。
[root@labhost ~]# docker run -d -p 5050:5000 mypyalpine
387d43c0920574fd8ea7c75db611c74de7fbc4bdb5be2961246fb8642ad7bc5c
docker: Error response from daemon: driver failed programming external connectivity on endpoint quizzical_bassi (0696007b82f3f83880fc6b43830b5b6680bf8cfc6cd48856fd7b504dc0e87abc): Bind for 0.0.0.0:5050 failed: port is already allocated.
[root@labhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
42b0bd3bf39c mypyalpine "python app.py" 4 hours ago Up 4 hours 0.0.0.0:5050->5000/tcp goofy_faraday
[root@labhost ~]# docker stop 42b0bd3bf39c
42b0bd3bf39c
[root@labhost ~]# docker rm 42b0bd3bf39c
42b0bd3bf39c
[root@labhost pyalpine]# docker run -d -p 5050:5000 --name myflask mypyalpine
d464fd0fa04893db4640cc3f2afe201ca07718978bc55f7a17bcc909cab25475
[root@labhost pyalpine]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d464fd0fa048 mypyalpine "python app.py" 3 seconds ago Up 2 seconds 0.0.0.0:5050->5000/tcp myflask
[root@labhost pyalpine]#
我们现在来访问一下flask网站:http://192.168.137.200:5050
可能大家对上面我们拉取的base image有点疑问,为什么选择python:3.7-alpine这个image作为我们的base image来构建我们的docker?原因很简单:身材苗条。我们可以看一下build好的image mypyalpine大小和一个ubuntu或者centos的image大小比较:
myflask这个是我用python:3.6这个base image构建的,925MB,将近1GB.
mypyalpine这个是我们用python:3.7-alpine构建的,只有83.8MB,不到100MB.
[root@labhost pyalpine]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mypyalpine latest 160344652c41 35 minutes ago 83.8MB
myflask latest c35e990ccb0c About an hour ago 925MB
python 3.6 e0373ff33a19 9 days ago 914MB
python 3.7-alpine 6ca3e0b1ab69 9 days ago 73.1MB
busybox latest c7c37e472d31 10 days ago 1.22MB
ubuntu latest 74435f89ab78 3 weeks ago 73.9MB
centos latest 831691599b88 3 weeks ago 215MB
最后,Enjoy your Docker!