【Docker】如何编写Dockerfile,深入理解 Dockerfile:构建精简且高效的容器镜像

文章目录

    • [1. 准备工作](#1. 准备工作)
    • [2. 创建 Dockerfile](#2. 创建 Dockerfile)
    • [3. 编写基本结构](#3. 编写基本结构)
    • [4. 指令详解](#4. 指令详解)
    • [5. 实战演练](#5. 实战演练)
    • [6. 构建镜像和运行容器](#6. 构建镜像和运行容器)
  • [`CMD` 和 `ENTRYPOINT` 之间的区别](#CMDENTRYPOINT 之间的区别)
    • [CMD 指令](#CMD 指令)
    • [ENTRYPOINT 指令](#ENTRYPOINT 指令)
    • 区别总结

Docker 是一种轻量级的容器化技术,使得应用程序和它们的依赖可以被打包到一个容器中,方便在不同环境中运行。Dockerfile 是用于定义 Docker 镜像的文本文件,其中包含了一系列的指令,这些指令描述了镜像中应该包含哪些内容和如何配置。

1. 准备工作

在开始编写 Dockerfile 之前,确保你已经在系统中安装了 Docker。你可以从 Docker 官方网站 获取安装步骤,或者阅读这里:https://blog.csdn.net/x1131230123/article/details/118032295

2. 创建 Dockerfile

首先,创建一个空的目录用于存放 Dockerfile 和相关文件。在该目录下创建一个文本文件并命名为 Dockerfile

3. 编写基本结构

一个简单的 Dockerfile 通常包含以下基本结构:

bash 复制代码
# 使用基础镜像
FROM base_image:tag

# 维护者信息
MAINTAINER your_name

# 设置工作目录
WORKDIR /app

# 复制本地文件到容器中
COPY ./local_files /app

# 安装依赖
RUN apt-get update && apt-get install -y dependency_package

# 暴露端口
EXPOSE 8080

# 定义启动命令
CMD ["command_to_run"]

以上是一个简单的 Dockerfile,接下来我们逐步介绍每个指令的作用。

4. 指令详解

FROM

FROM 指令用于指定基础镜像,即你的应用程序将在其基础上构建。可以选择官方镜像,也可以选择其他已有的镜像。例如:

dockerfile 复制代码
FROM ubuntu:20.04

MAINTAINER

MAINTAINER 指令用于设置维护者的信息。

dockerfile 复制代码
MAINTAINER Your Name <your.email@example.com>

WORKDIR

WORKDIR 指令用于设置工作目录,即在容器中执行后续指令时的工作目录。

dockerfile 复制代码
WORKDIR /app

COPY

COPY 指令用于将本地文件复制到容器中。可以复制单个文件,也可以复制整个目录。

dockerfile 复制代码
COPY ./local_files /app

RUN

RUN 指令用于在镜像中执行命令,例如安装依赖。

dockerfile 复制代码
RUN apt-get update && apt-get install -y dependency_package

EXPOSE

EXPOSE 指令用于声明容器运行时将监听的端口。这只是一个元数据,实际运行时需要使用 -p 选项映射端口。

dockerfile 复制代码
EXPOSE 8080

CMD

CMD 指令用于定义容器启动时执行的默认命令。

dockerfile 复制代码
CMD ["command_to_run"]

5. 实战演练

接下来,我们通过一个简单的 Node.js 应用演示如何编写 Dockerfile。

dockerfile 复制代码
FROM node:14

WORKDIR /app

COPY package.json package-lock.json /app/

RUN npm install

COPY . /app/

EXPOSE 3000

CMD ["npm", "start"]

在上述示例中,我们使用 Node.js 的官方镜像作为基础镜像,设置工作目录,复制 package.jsonpackage-lock.json 安装依赖,复制所有文件到工作目录,声明监听端口为 3000,并定义启动命令为 npm start

6. 构建镜像和运行容器

保存好 Dockerfile 后,可以使用以下命令构建镜像。在Docker中,docker build -t my-node-app . 中的小数点代表当前上下文的路径。这个路径是构建过程中 Docker 引擎查找 Dockerfile 和其他构建上下文的文件的位置。

具体来说,docker build 命令会将指定的路径(这里是小数点 .)作为构建上下文。构建上下文是构建过程中用来查找 Dockerfile 和其他构建文件的目录。在这个例子中,. 表示当前目录,即你运行 docker build 命令的目录。

当你运行 docker build -t my-node-app . 时,Docker 引擎会在当前目录下寻找 Dockerfile 文件,并将该目录及其所有内容作为构建上下文。这样,Dockerfile 就能够引用当前目录中的文件,并将它们添加到 Docker 镜像中。在给定目录之外的文件是不能通过Docker指令操作的,比如想用COPY去拷贝别的目录的文件到镜像中。

bash 复制代码
docker build -t my-node-app .

然后,可以运行容器:

bash 复制代码
docker run -p 3000:3000 my-node-app

现在,你的 Node.js 应用将在 Docker 容器中运行,并可以通过 http://localhost:3000 访问。

CMDENTRYPOINT 之间的区别

CMD 指令

CMD 指令用于定义容器启动时执行的默认命令。它有以下几种形式:

  1. CMD ["executable","param1","param2"] (exec 格式,推荐): 在指定的可执行文件内运行参数。

    dockerfile 复制代码
    CMD ["npm", "start"]
  2. CMD ["param1","param2"] (作为 ENTRYPOINT 的默认参数): 提供给 ENTRYPOINT 指令的默认参数。

    dockerfile 复制代码
    CMD ["npm", "start"]
  3. CMD command param1 param2 (shell 格式) : 在 /bin/sh -c 中执行命令。

    dockerfile 复制代码
    CMD npm start

CMD 的主要作用是为容器提供默认的执行命令,但可以被在运行容器时指定的命令覆盖。

ENTRYPOINT 指令

ENTRYPOINT 指令用于配置容器启动时执行的默认可执行文件。它有以下几种形式:

  1. ENTRYPOINT ["executable", "param1", "param2"] (exec 格式,推荐): 在指定的可执行文件内运行参数。

    dockerfile 复制代码
    ENTRYPOINT ["npm", "start"]
  2. ENTRYPOINT command param1 param2 (shell 格式) : 在 /bin/sh -c 中执行命令。

    dockerfile 复制代码
    ENTRYPOINT npm start

使用 ENTRYPOINT 的主要目的是将容器配置为像可执行程序一样运行。它的参数可以被 CMD 覆盖,但不会被完全替代。如果给 docker run 提供了参数,它们将追加到 ENTRYPOINT 的参数之后。

区别总结

  • CMD 提供容器默认的执行命令,可以被运行容器时传入的命令覆盖。
  • ENTRYPOINT 配置容器启动时执行的默认可执行文件,可以被运行容器时传入的命令追加到其参数之后。

综合来说,CMD 通常用于提供应用的默认启动命令,而 ENTRYPOINT 通常用于配置容器以类似可执行程序的方式运行。你也可以同时使用它们,以 ENTRYPOINT 提供基础执行文件,而 CMD 提供默认参数。

相关推荐
雪域迷影8 小时前
PostgreSQL Docker Error – 5432: 地址已被占用
数据库·docker·postgresql
福大大架构师每日一题9 小时前
22.1 k8s不同role级别的服务发现
容器·kubernetes·服务发现
莹雨潇潇9 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
tangdou36909865510 小时前
1分钟搞懂K8S中的NodeSelector
云原生·容器·kubernetes
tangdou36909865513 小时前
Docker系列-5种方案超详细讲解docker数据存储持久化(volume,bind mounts,NFS等)
docker·容器
later_rql13 小时前
k8s-集群部署1
云原生·容器·kubernetes
漫无目的行走的月亮16 小时前
在Docker中运行微服务注册中心Eureka
docker
大G哥18 小时前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
大道归简19 小时前
Docker 命令从入门到入门:从 Windows 到容器的完美类比
windows·docker·容器
zeruns80220 小时前
如何搭建自己的域名邮箱服务器?Poste.io邮箱服务器搭建教程,Linux+Docker搭建邮件服务器的教程
linux·运维·服务器·docker·网站