目标: 用 Docker 部署一个用 Python 编写的 Web 应用。
首先部署整个流程:
基础镜像(python)-->flask-->部署python应用
web框架 flask django
代码功能:
如果当前环境中有"NAME"这个环境变量,就把它打印在"Hello"后,否则就打印"Hello world",最后再打印出当前环境的 hostname。
[root@yixuan ~]# mkdir python_app
[root@yixuan ~]# cd python_app/
[root@yixuan python_app]# vim app.py
from flask import Flask
import socket
import os
app = Flask(__name__)
@app.route('/')
def hello():
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
应用依赖:
定义在同目录下的 requirements.txt 文件里,内容如下:
[root@yixuan python_app]# vim requirements.txt
Flask
Dockerfile制作容器镜像:
# vim Dockerfile
FROM python:2.7-slim
WORKDIR /app
ADD . /app
RUN pip install --trusted-host pypi.python.org -r requirements.txt
EXPOSE 80
ENV NAME World
CMD ["python", "app.py"]
Dockerfile文件说明:
FROM python:2.7-slim
# 使用官方提供的 Python 开发镜像作为基础镜像
# 指定"python:2.7-slim"这个官方维护的基础镜像,从而免去安装 Python 等语言环境的操作。:
WORKDIR /app
# 将工作目录切换为 /app,意思是在这一句之后,Dockerfile 后面的操作都以这一句指定的 /app 目录作为当前目录。
ADD . /app
# 将当前目录下的所有内容复制到 /app 下 Dockerfile 里的原语并不都是指对容器内部的操作。比如 ADD,指的是把当前目录(即 Dockerfile 所在的目录)里的文件,复制到指定容器内的目录当中。
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 使用 pip 命令安装这个应用所需要的依赖
EXPOSE 80
# 允许外界访问容器的 80 端口
ENV NAME World
# 设置环境变量
CMD ["python", "app.py"]
# 设置容器进程为:python app.py,即:这个 Python 应用的启动命令,这里app.py 的实际路径是 /app/app.py。CMD ["python", "app.py"] 等价于 "docker run python app.py"。
现在目录结构:
[root@yixuan python_app]# ls
Dockerfile app.py requirements.txt
构建镜像:
[root@yixuan python_app]# docker build -t testpython .
-t 给这个镜像加一个 Tag
Dockerfile 中的每个原语执行后,都会生成一个对应的镜像层。即使原语本身并没有明显地修改文件的操作(比如,ENV 原语),它对应的层也会存在。只不过在外界看来,这个层是空的。
查看结果:
[root@yixuan python_app]# docker images
REPOSITORY TAG IMAGE ID ...
testpython latest 16bc21f3eea3
启动容器:
[root@yixuan python_app]# docker run -it -p 4000:80 testpython /bin/bash
查看容器:
[root@yixuan python_app]# docker ps
CONTAINER ID IMAGE COMMAND CREATED
ce02568e64ce testpython "/bin/bash" About a minute ago
进入容器:
[root@yixuan python_app]# docker exec -it ce02568 /bin/bash
root@ce02568e64ce:/app# python app.py & #将python运行起来
访问容器内应用:
[root@yixuan ~]# curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> f201f6855136<br/>
实战练习
1.创建一个jenkins的Dockerfile
[root@yixuan ~]# mkdir tomcat
[root@yixuan ~]# cd tomcat/
[root@yixuan tomcat]# vim Dockerfile
# This my first jenkins Dockerfile
# Version 1.0
FROM daocloud.io/library/centos:7
MAINTAINER yixuan
ENV JAVA_HOME /usr/local/jdk1.8.0_211
ENV TOMCAT_HOME /usr/local/apache-tomcat-8.5.47
ENV PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
ENV CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
ADD apache-tomcat-8.5.47.tar.gz /usr/local/
ADD jdk-8u211-linux-x64.tar.gz /usr/local/
RUN rm -rf /usr/local/apache-tomcat-8.5.47/webapps/*
ADD jenkins.war /usr/local/apache-tomcat-8.5.47/webapps
RUN rm -rf apache-tomcat-8.5.47.tar.gz apache-tomcat-8.5.47.tar.gz
EXPOSE 8080
ENTRYPOINT ["/usr/local/apache-tomcat-8.5.47/bin/catalina.sh","run"] #运行的命令
[root@yixuan tomcat]# pwd
/root/tomcat
[root@yixuan tomcat]# ls #将jdk与tomcat还有jenkins的包上传到tomcat目录中
apache-tomcat-8.5.47.tar.gz Dockerfile jdk-8u211-linux-x64.tar.gz jenkins.war
[root@yixuan tomcat]# docker build -t jenkins:v1 .
[root@yixuan tomcat]# docker run -itd --name jenkins1 -p 8081:8080 jenkins:v1