docker学习: 2. 构建镜像Dockerfile

如果我们要自己制作一个像nginx一样的镜像,怎么做呢?

docker 容器内就是一个独立的系统环境,想想如果在这样一个系统上,要安装 nginx 服务,怎么做呢?

需要执行一些命令、复制一些文件进来,然后启动服务。

制作镜像自然也要进行这样的过程,不过可以自动化。

只要在 dockerfile 里声明要做哪些事情,docker build 的时候就会根据这个 dockerfile 来自动化构建出一个镜像来。

比如这样:

js 复制代码
FROM node:latest

WORKDIR /app

COPY . .

RUN npm config set registry https://registry.npmmirror.com/

RUN npm install -g http-server

EXPOSE 8080

CMD ["http-server", "-p", "8080"]

这些指令的含义如下:

  • FROM:基于一个基础镜像来修改
  • WORKDIR:指定当前工作目录
  • COPY:把容器外的内容复制到容器内
  • EXPOSE:声明当前容器要访问的网络端口,比如这里起服务会用到 8080
  • RUN:在容器内执行命令
  • CMD:容器启动的时候执行的命令

我们先通过 FROM 继承了 node 基础镜像,里面就有 npm、node 这些命令了。

通过 WORKDIR 指定当前目录。

然后通过 COPY 把 Dockerfile 同级目录下的内容复制到容器内,这里的 . 也就是 /app 目录

之后通过 RUN 执行 npm install,全局安装 http-server

通过 EXPOSE 指定要暴露的端口

CMD 指定容器跑起来之后执行的命令,这里就是执行 http-server 把服务跑起来。

把这个文件保存为 Dockerfile,然后在同级添加一个 index.html。

然后通过 docker build 就可以根据这个 dockerfile 来生成镜像。

js 复制代码
docker build -t aaa:ccc .

aaa 是镜像名,ccc 是镜像的标签。

-t 是 --tag 的简写形式,翻译过来就是给镜像打标签 (Tag),作用是为你即将构建的镜像指定一个易识别的名称和标签。

镜像标签最主要的作用是标记镜像的版本,比如v1.0、v2.1、latest、beta等。

js 复制代码
# 构建v1.0版本的web服务镜像 
docker build -t my-web:v1.0 . 
# 构建v2.0版本的web服务镜像 
docker build -t my-web:v2.0 . 
# 构建测试版镜像 
docker build -t my-web:beta .

可以给同一个镜像 ID 打多个标签,相当于给镜像起别名,方便区分。

aaa:ccc 后面的这个 . 代表构建上下文(Build Context) 的路径,. 就是告诉 Docker 从当前目录 (你执行这条命令的目录)读取所有文件作为构建上下文。Dockerfile 中 COPY、ADD 等复制文件的指令,只能复制构建上下文目录内 的文件,无法复制上下文之外的文件(比如上级目录 ../)。

这时你在 desktop 的 images 列表里就可以看到这个镜像了。

运行起来后,我们在 files 里看看 /app 下是啥内容:

双击 index.html,可以看到这就是我们 build 镜像的时候 COPY 进去的文件。

但是我们想修改静态文件怎么办呢?

进入容器内改太麻烦,不如把这个 /app 目录设置为挂载点吧。

这样改下 Dockerfile:

然后重新 build 出一个镜像来:

js 复制代码
docker build -t aaa:ddd -f 2.Dockerfile .

因为现在不是默认的 Dockerfile 了,需要用 -f 指定下 dockefile 的文件名。

这次我把我的桌面目录作为数据卷挂载到 /app 目录了:

容器跑起来后可以看到确实挂载上去了,也标识为了 mount:

浏览器访问下:

在 inspect 这里也可以看到挂载的目录:

有同学说,就算不在 dockerfile 里指定 VOLUME,我还是可以 docker run 的时候通过 -v 挂载数据卷呀。

那我为啥还要指定 VOLUME?

在 dockerfile 里指定 VOLUME 之后,如果你 docker run 的时候没有带 -v,那会放在一个临时的目录里。

docker 会随机生成一个目录作为数据卷挂载上去,inspect 可以看到这时候的路径是一个临时的目录:

这样就算你删了容器,数据也可以在这里找回。

设想下,如果你跑了个 mysql 容器,存了很多数据,但是跑容器的时候没指定数据卷。有一天,你把容器删了,所有数据都没了,可不可怕?

为了避免这种情况,mysql 的 dockerfile 里是必须声明 volume 的,这样就算你没通过 -v 指定数据卷,将来也可以找回数据。

在镜像详情可以看到 mysql 的 dockerfile,确实声明了 volume。

相关推荐
csdn_aspnet14 小时前
macOS 10 、Docker 玩轉 MySQL
运维·mysql·macos·docker·容器·mac
对象存储与RustFS16 小时前
Jenkins 的构建产物别堆在控制器磁盘:用 RustFS 当它的 S3 工件仓库
后端·docker·云原生
java_logo1 天前
Docker 部署 DeepSeek Harness(moelin):轻松搭建带登录的本地 AI Agent 平台
运维·docker·容器·ai agent·deepseek·harness·轩辕镜像
xbzb1 天前
容器 IP 每次重建都变?docker network 五种模式与自定义网桥固定地址
网络·docker·容器·ip·network·固定
打工仔折腾 AI2 天前
Changedetection.io 网页变动监控:Docker 部署、通知配置与公网暴露实践
运维·人工智能·后端·python·docker·容器·性能优化
xbzb2 天前
自建镜像仓库:registry 一条命令 + harbor 部署、授权、跨库同步与卸载
docker·harbor·镜像·仓库·同步·registry
wz97543 天前
Docker 从 systemd 托管容器、overlay2 存储驱动到 Compose 多容器实战
spring cloud·docker·eureka
新*3 天前
ES 7.17 三节点 Docker 集群接入 IK 自定义词典:一次从丢插件到热更新的完整排障
运维·elasticsearch·docker·中文分词·ik分词
小白的码BUG之路3 天前
Jenkins -- gitee+docker+harbor+k8s 部署项目
docker·gitee·jenkins
AlfredZhao3 天前
Docker Compose 平滑切换环境变量文件,容器配置不残留
docker