ref="/tag/2019/" style="color:#479099;font-weight:bold;">Docker镜像包含什么内容
很多人刚开始接触Docker时,总以为镜像就是个“打包好的软件”,点一下就能跑。其实没那么简单。Docker镜像更像是一个“快照”,记录了运行某个应用所需的一切。
它不是简单的压缩包,而是一层层叠加的文件系统,每一层都代表一次变更。比如你先装了个Ubuntu系统,再安装Python,然后拷贝代码,每一步都会生成一层。这些层是只读的,最终组合成一个完整的、可启动的镜像。
基础操作系统环境
大多数Docker镜像都基于某个Linux发行版,比如Alpine、Ubuntu或CentOS。但注意,它不包含完整的内核——容器共享宿主机的内核。所以镜像里只是用户空间的程序和库。比如你用FROM ubuntu:20.04,镜像就包含了Ubuntu 20.04的目录结构、包管理器和基础命令(如ls、apt等)。
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3上面这段Dockerfile中,第一行拉取的就是一个最小化的Ubuntu环境,第二行在其基础上安装Python3,这两步各自形成一层。
应用程序代码和依赖
你的Python脚本、Node.js项目或者Java JAR包,都会被打包进镜像。同时,项目所需的依赖也会一并安装。比如一个Flask应用,除了代码,还需要pip安装flask、requests等库。这些都被固化在镜像中,保证在哪运行都一致。
举个例子,你在公司开发完代码,本地测试没问题,扔到服务器上却报错说“找不到模块”。这种“在我机器上能跑”的经典问题,用Docker镜像就能避免——因为环境已经完整封进去了。
配置文件和环境变量
数据库连接地址、API密钥、日志级别这些配置,通常会通过配置文件或环境变量写入镜像。虽然敏感信息建议运行时注入,但默认配置可以预先设定。比如Nginx镜像里就内置了nginx.conf,启动时直接生效。
环境变量可以用ENV指令设置:
ENV DATABASE_HOST=db.example.com
ENV LOG_LEVEL=info这样容器启动后,应用可以直接读取这些值,不用重新改代码。
元数据:启动命令和端口声明
镜像还包含一些“说明书”性质的信息。比如CMD或ENTRYPOINT定义了容器启动时默认运行什么命令。如果你不做改动,run起来就自动执行这个。
还有EXPOSE指令,声明服务监听的端口。比如Web应用常用80或3000端口,写上EXPOSE 3000,别人一看就知道怎么访问。
为什么镜像不能修改?
镜像是只读的,这是设计上的关键点。一旦构建完成,任何内容都不能直接更改。你要更新代码或配置,得重新构建新镜像。这样做虽然多了一步,但换来的是可复现性和版本控制能力。就像发布App版本一样,v1.0和v1.1分得清清楚楚。
实际使用中,很多团队会把镜像推送到私有仓库,配合CI/CD流程,代码一提交,自动构建并打上版本标签,运维直接拉对应版本运行,整个过程干净利落。