docker--Dockerfile、构建 python 镜像

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: docker--Dockerfile、构建 python 镜像

前戏


镜像是容器的基础,每次执行 docker run 的时候都会指定哪个镜像作为容器运行的基础,我们之前的例子都是使用来自 docker hub 的镜像。直接使用这些镜像只能满足一定的需求,当镜像无法满足我们的需求时,就得自定制这些镜像。

镜像的定制就是定制每一层所添加的配置、文件。如果把每一层修改,安装,构建,操作的命令都写入到一个脚本,用脚本来构建、定制镜像,这个脚本就是 Dockerfile。

Dockerfile 是一个文本文件,其内部包含一条条指令, 每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建

Dockerfile 可以说是一种可以被 Docker 程序解释的脚本,Dockerfile 是由一条条的命令组成的,每条命令对应 linux 下面的一条命令,Docker 程序将这些 Dockerfile 指令在翻译成真正的 linux 命令,其有自己的书写方式和支持的命令,docker 程序读取 Dockerfile 并根据指令生成 Docker 镜像,相比手动制作镜像的方式,Dockerfile 更能直观的展示镜像是怎么产生的。有了写好的各种各样的 Dockerfile 文件,当后期某个镜像有额外的需求时,只要在之前的 Dockerfile 添加或者修改相应的操作即可重新生成新的 Docker 镜像,避免了重复手动制作镜像的麻烦


Dockerfile的命令


FROM centos # 使用基础镜像 centos。在整个 dockerfile 文件中,除了注释之外的第一行,要是 FROM,用于指定父镜像
FROM ubuntu:14.04 # 带有 tag 的 base image
LABEL version=“1.0” # 容器元信息,帮助信息,Metadata,类似于代码注释
LABEL maintainer=“zouzou0214"
# 对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!
RUN yum update && yum install -y vim \
    Python-dev #反 斜线换行
RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”
WORKDIR /root # 相当于 linux 的 cd 命令,改变目录,尽量使用绝对路径!!!不要用 RUN cd
WORKDIR /test # 如果没有就自动创建
WORKDIR demo # 再进入 demo 文件夹
RUN pwd     # 打印结果是 /test/demo
ADD and COPY 
ADD hello /  # 把本地文件添加到镜像中(和 Dockerfile 同级),把本地的 hello 可执行文件拷贝到镜像的/目录
ADD test.tar.gz /  # 添加到根目录并解压
WORKDIR /root
ADD hello test/  # 进入 /root/ 添加 hello 可执行命令到 test 目录下,也就是 /root/test/hello 一个绝对路径
COPY hello test/  # 等同于上述 ADD 效果
'''
ADD 与COPY
   - 优先使用 ADD 命令
    -ADD 除了COPY 功能还有解压功能
添加远程文件/目录使用 curl 或 wget
'''
ENV # 环境变量,尽可能使用 ENV 增加可维护性
ENV MYSQL_VERSION 5.6 #设置一个 mysql 常量
RUN yum install -y mysql-server=“${MYSQL_VERSION}” 
------这里需要稍微理解一下了-------中级知识---
VOLUME and EXPOSE 
存储和网络
RUN and CMD and ENTRYPOINT
RUN:执行命令并创建新的 Image Layer
CMD:设置容器启动后默认执行的命令和参数
ENTRYPOINT:设置容器启动时运行的命令
Shell 格式和 Exec 格式
RUN yum install -y vim
CMD echo ”hello docker”
ENTRYPOINT echo “hello docker”
Exec 格式
RUN [“apt-get”,”install”,”-y”,”vim”]
CMD [“/bin/echo”,”hello docker”]
ENTRYPOINT [“/bin/echo”,”hello docker”]
通过 shell 格式去运行命令,会读取 $name 指令,而 exec 格式是仅仅的执行一个命令,而不是 shell 指令
cat Dockerfile
    FROM centos
    ENV name Docker
    ENTRYPOINT [“/bin/echo”,”hello $name”]# 这个仅仅是执行 echo 命令,读取不了 shell 变量
    ENTRYPOINT  [“/bin/bash”,”-c”,”echo hello $name"]
CMD
容器启动时默认执行的命令
如果docker run指定了其他命令(docker run -it [image] /bin/bash ),CMD命令被忽略
如果定义多个CMD,只有最后一个执行
ENTRYPOINT
让容器以应用程序或服务形式运行
不会被忽略,一定会执行
最佳实践:写一个shell脚本作为entrypoint
COPY docker-entrypoint.sh /usr/local/bin
ENTRYPOINT [“docker-entrypoint.sh]
EXPOSE 27017
CMD [“mongod”]
[root@master home]# more Dockerfile
FROm centos
ENV name Docker
#CMD ["/bin/bash","-c","echo hello $name"]
ENTRYPOINT ["/bin/bash","-c","echo hello $name”]


创建自己的容器镜像


1.先准备一段flask代码

myflask.py

from flask import Flask
    app=Flask(__name__)
    @app.route('/')
    def hello():
        return "hello docker,i am is zouzou"
    if __name__=="__main__":
        app.run(host='0.0.0.0',port=8080)

2.准备传到docker容器里的文件

[root@HH tmp]# ls
CentOS-Base.repo  Dockerfile  epel.repo  myflask.py

3.制作Dockerfile

FROM centos
LABEL maintainer="zouzou0214"
ADD CentOS-Base.repo /etc/yum.repos.d/
ADD epel.repo /etc/yum.repos.d/
RUN yum clean all
RUN yum install python-pip -y
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple flask
COPY myflask.py /app/
WORKDIR /app/
EXPOSE 8081
CMD ["python","myflask.py"]
  • 1.引入一个 centos 镜像,为基础镜像
  • 2.作者注释信息
  • 3.添加本地的两个 yum 文件,到容器的 /etc/yum.repos.d/ 底下
  • 4.清空 yum 缓存
  • 5.yum 安装 pip 工具
  • 6.pip 安装 flask 模块,指定清华源
  • 7.拷贝本地的 flask 代码,到容器的 /app/ 目录下
  • 8.切换工作目录,到 /app 底下
  • 9.暴露容器的 8081 端口,然后在运行镜像时候,加上 -p 参数,指定端口映射
  • 10.执行命令,运行 flask

4.构建 docker 镜像

docker build -t zouzu0214/my-docker-flask .

注意:最后面有个.(点)代表从当前目录build

  • 构建当前目录的 Dcokerfile,然后构建出一个名为 zouzou0214/my-docker-flask 这个的镜像文件
  • -t tag 参数,给镜像加上标记名
  • dockerhub 账户名:zouzou0214,dockerhub账户名/镜像名 ,是为了后面讲 docker 镜像,推送到 dockerhub

5.查看镜像是否构建成功:docker images

[root@HH tmp]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
zouzu0214/my-docker-flask   latest              845652a3022e        12 seconds ago      346MB
centos                      latest              67fa590cfc1c        5 weeks ago         202MB

我本地是没有 centos 镜像的,会去先下载一个 centos 镜像,然后基于该镜像构建

6.运行镜像

[root@HH tmp]# docker run -d -p 9000:8081 8456
bcd4e98ba419f5eaf3c9f43e64d9b1dd2558fddb2316be84b46fdf656318ab64

docker run -p 9000:8081 -d 8456

-p 映射 9000 端口到容器的 8081

-d 后台运行

8456  镜像id

7.查看已经运行的docker实例

[root@HH tmp]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
44a53f62f533        76a7                "/sbin/tini -- /usr/…"   11 hours ago        Up 11 hours         50000/tcp, 0.0.0.0:8000->8080/tcp   MyJenkins


RUN、CMD、ENTRYPOINT 之间的区别


这三个命令都是执行命令的,那它们之间有什么区别呢?先来熟悉两个概念

  • shell 命令格式:RUN yum install -y python
  • exec 命令格式:RUN [ "yum","install" ,"-y" ,"python"]

我们有一个centos:7的基础镜像

案例一:写一个 dockerfile,内容如下

FROM centos:7
RUN echo "my is run..."
CMD ["echo","my","is","cmd"]
ENTRYPOINT ["echo","my","is","entrypoint"]

构建镜像

docker build -t centos:v1 .

启动这个镜像

[root@WC ~]# docker run centos:v1
my is entrypoint echo my is cmd

由上面的例子我们可以看出来,RUN 命令是作用于镜像的,在构建镜像的时候会执行 RUN 命令

而 CMD 和 ENTRYPOINT 是作用于容器的,在容器启动时执行的,会将 CMD 做为一个参数传递给 ENTRYPOINT ,所以上面输出的是 my is entrypoint echo my is cmd

案例二:修改 dockerfile,修改后的如下

FROM centos:7
CMD ["echo","my","is","cmd1"]
CMD ["echo","my","is","cmd2"]
ENTRYPOINT ["echo","my","is","entrypoint1"]
ENTRYPOINT ["echo","my","is","entrypoint2"]

构建镜像

[root@WC ~]# docker build -t centos:v2 .
Sending build context to Docker daemon    854kB
Step 1/5 : FROM centos:7
 ---> 5e35e350aded
Step 2/5 : CMD ["echo","my","is","cmd1"]
 ---> Running in a5a50c279343
Removing intermediate container a5a50c279343
 ---> 580f6c1ca1d8
Step 3/5 : CMD ["echo","my","is","cmd2"]
 ---> Running in bda45cc4de5f
Removing intermediate container bda45cc4de5f
 ---> 98daa774b962
Step 4/5 : ENTRYPOINT ["echo","my","is","entrypoint1"]
 ---> Running in f181f49673e7
Removing intermediate container f181f49673e7
 ---> f477e3841a4a
Step 5/5 : ENTRYPOINT ["echo","my","is","entrypoint2"]
 ---> Running in cc4b61298119
Removing intermediate container cc4b61298119
 ---> c7f3fbb0365a
Successfully built c7f3fbb0365a
Successfully tagged centos:v2

还是没有执行 CMD 和 ENTRYPOINT,启动容器

[root@WC ~]# docker run centos:v2
my is entrypoint2 echo my is cmd2

结果:有多个 CMD 和 ENTRYPOINT 时,只执行最后的一个,会将最后一个的 CMD 作为最后一个 ENTRYPOINT 的参数

案例三:修改 dockerfile,修改后的如下

FROM centos:7
CMD ["-ef"]
ENTRYPOINT ["ps"]

构建镜像

[root@WC ~]# docker build -t centos:v3 .
Sending build context to Docker daemon  854.5kB
Step 1/3 : FROM centos:7
 ---> 5e35e350aded
Step 2/3 : CMD ["-ef"]
 ---> Running in 3c10444a83a0
Removing intermediate container 3c10444a83a0
 ---> 36d8da189295
Step 3/3 : ENTRYPOINT ["ps"]
 ---> Running in e7751f2f9c64
Removing intermediate container e7751f2f9c64
 ---> ba96ea2aebf5
Successfully built ba96ea2aebf5
Successfully tagged centos:v3

启动镜像

可以看出会将 ENTRYPOINT 和 CMD 的执行结果显示出来,我们还可以在启动容器的时候加上参数,会替换掉 CMD 的参数


总结:

  • RUN:在构建镜像的时候执行,作用于镜像层面
  • ENTRYPOINT:在容器启动的时候执行,作用于容器层,dockerfile 里有多条时只允许执行最后一条
  • CMD:在容器启动的时候执行,作用于容器层,dockerfile 里有多条时只允许执行最后一条,容器启动后执行默认的命令或者参数,允许被修改

注意:如果 ENTRYPOINT 使用的是 exec 的格式,则会将 CMD 当做参数,如果是 shell,则不会将 CMD 当做参数


构建 python 镜像


先来使用 fastapi 写一段程序

from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def index():
    return "this is v1 pages"
@app.get("/app")
async def index():
    return "我是 v1 的 app 页面"
if __name__ == '__main__':
    import uvicorn
    uvicorn.run('main:app', host='0.0.0.0', port=8008, reload=True, debug=True, workers=1)

在来写我们的 dockerfile

FROM python:3.9.13-alpine3.16  # 这个镜像只有 10 多 M
LABEL maintainer="zouzou0214"
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple fastapi
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple uvicorn
COPY main.py /app/
WORKDIR /app/
EXPOSE 8008
CMD ["python","main.py"]

打镜像

docker build -t zouzou0214/myapp:v1 .

启动镜像

[root@master1 db]# docker run -d --name myapp -p 8999:8008 zouzou0214/myapp:v1
ed39fdc5991c84c9ee884739c54ec05b0bce671cd06e4d90f65ca6896a256ae4

浏览器访问


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9天前
|
机器学习/深度学习 设计模式 API
Python 高级编程与实战:构建 RESTful API
本文深入探讨了使用 Python 构建 RESTful API 的方法,涵盖 Flask、Django REST Framework 和 FastAPI 三个主流框架。通过实战项目示例,详细讲解了如何处理 GET、POST 请求,并返回相应数据。学习这些技术将帮助你掌握构建高效、可靠的 Web API。
|
9天前
|
机器学习/深度学习 设计模式 测试技术
Python 高级编程与实战:构建自动化测试框架
本文深入探讨了Python中的自动化测试框架,包括unittest、pytest和nose2,并通过实战项目帮助读者掌握这些技术。文中详细介绍了各框架的基本用法和示例代码,助力开发者快速验证代码正确性,减少手动测试工作量。学习资源推荐包括Python官方文档及Real Python等网站。
|
15天前
|
存储 运维 应用服务中间件
Docker Image即Docker镜像
Docker 镜像是 Docker 容器的基础,包含了运行应用程序所需的一切。通过 Dockerfile 可以方便地创建自定义镜像,并且利用 Docker 提供的命令可以轻松管理和使用这些镜像。掌握 Docker 镜像的创建、管理和使用,是进行容器化应用开发和部署的基础技能。希望本文能帮助读者更好地理解 Docker 镜像的概念和操作,提高开发和运维效率。
76 13
|
1月前
|
消息中间件 Kafka 流计算
docker环境安装kafka/Flink/clickhouse镜像
通过上述步骤和示例,您可以系统地了解如何使用Docker Compose安装和配置Kafka、Flink和ClickHouse,并进行基本的验证操作。希望这些内容对您的学习和工作有所帮助。
168 28
|
9天前
|
机器学习/深度学习 设计模式 API
Python 高级编程与实战:构建微服务架构
本文深入探讨了 Python 中的微服务架构,介绍了 Flask、FastAPI 和 Nameko 三个常用框架,并通过实战项目帮助读者掌握这些技术。每个框架都提供了构建微服务的示例代码,包括简单的 API 接口实现。通过学习本文,读者将能够使用 Python 构建高效、独立的微服务。
|
9天前
|
消息中间件 分布式计算 并行计算
Python 高级编程与实战:构建分布式系统
本文深入探讨了 Python 中的分布式系统,介绍了 ZeroMQ、Celery 和 Dask 等工具的使用方法,并通过实战项目帮助读者掌握这些技术。ZeroMQ 是高性能异步消息库,支持多种通信模式;Celery 是分布式任务队列,支持异步任务执行;Dask 是并行计算库,适用于大规模数据处理。文章结合具体代码示例,帮助读者理解如何使用这些工具构建分布式系统。
|
14天前
|
JavaScript Shell C#
多种脚本批量下载 Docker 镜像:Shell、PowerShell、Node.js 和 C#
本项目提供多种脚本(Shell、PowerShell、Node.js 和 C#)用于批量下载 Docker 镜像。配置文件 `docker-images.txt` 列出需要下载的镜像及其标签。各脚本首先检查 Docker 是否安装,接着读取配置文件并逐行处理,跳过空行和注释行,提取镜像名称和标签,调用 `docker pull` 命令下载镜像,并输出下载结果。使用时需创建配置文件并运行相应脚本。C# 版本需安装 .NET 8 runtime。
91 1
|
25天前
|
存储 人工智能 程序员
通义灵码AI程序员实战:从零构建Python记账本应用的开发全解析
本文通过开发Python记账本应用的真实案例,展示通义灵码AI程序员2.0的代码生成能力。从需求分析到功能实现、界面升级及测试覆盖,AI程序员展现了需求转化、技术选型、测试驱动和代码可维护性等核心价值。文中详细解析了如何使用Python标准库和tkinter库实现命令行及图形化界面,并生成单元测试用例,确保应用的稳定性和可维护性。尽管AI工具显著提升开发效率,但用户仍需具备编程基础以进行调试和优化。
222 9
|
1月前
|
网络协议 Linux 网络安全
docker centos镜像 npm安装包时报错“npm ERR! code ECONNRESET”
通过上述步骤,您可以有效解决在 Docker 中使用 CentOS 镜像安装 npm 包时遇到的 "npm ERR! code ECONNRESET" 错误。希望这些方法能帮助您顺利进行 npm 包的安装。
143 26
|
1天前
|
Docker Python 容器
Docker——阿里云服务器使用Docker部署python项目全程小记
本文记录了我在阿里云服务器上使用Docker部署python项目(flask为例)的全过程,在这里记录和分享一下,希望可以给大家提供一些参考。