前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Dockerfile的一些用法和最佳实践记录

Dockerfile的一些用法和最佳实践记录

作者头像
panzhixiang
发布2024-10-30 19:36:23
发布2024-10-30 19:36:23
23600
代码可运行
举报
文章被收录于专栏:panzhixiangpanzhixiang
运行总次数:0
代码可运行

记录一些在使用Dockerfile过程中遇到的用法和最佳实践。

COPY 和 ADD 命令的区别

COPYADD 都是 Dockerfile 的指令,都可以将文件或目录从主机复制到 docker 镜像中。但是,它们之间存在一些区别:

功能: COPY 指令将从构建上下文中复制新的文件或目录,并将它们添加到镜像的文件系统中指定的路径。 ADD 指令也有类似的功能,但是它还有两个额外的功能。首先,如果源文件是一个 tar 文件,ADD 将自动解压这个 tar 文件。其次,ADD 指令支持使用 URL 作为源文件,会自动下载这个 URL 指向的文件。

使用建议: 由于 ADD 指令具有更多的功能,所以它的行为也更复杂,更不可预测。 Docker 官方建议,只有在你确实需要 ADD 提供的额外功能时才使用它,否则默认使用 COPY 指令。这样可以使 Dockerfile 更易于理解,更具可维护性。

示例:

  • 使用 COPY 指令:
代码语言:javascript
代码运行次数:0
复制
COPY test.txt /data/

将当前目录下的 test.txt 文件复制到镜像的 /data/ 目录下。

  • 使用 ADD 指令:
代码语言:javascript
代码运行次数:0
复制
ADD https://example.com/test.txt /data/

将远程的 test.txt 文件下载并复制到镜像的 /data/ 目录下。

多阶段构建

Dockerfile的多阶段编译是Docker 17.05版本以后引入的一种新特性,它可以让你在一个Dockerfile中使用多个FROM指令。每个FROM指令可以使用不同的基础镜像,并且开始一个新的构建阶段。每个阶段是完全独立的,可以被认为是一个临时的中间镜像。

多阶段构建的优点主要有两个:一是可以避免最终生产的Docker镜像变得过大;二是可以避免在构建过程中在镜像中留下不必要的工具和依赖。

以下是一个使用多阶段构建的例子,它首先使用golang镜像来编译Go应用程序,然后在新的阶段使用基于alpine的较小镜像来运行该应用程序:

代码语言:javascript
代码运行次数:0
复制
# Stage 1: Build the Go binary
FROM golang:1.14.2 as builder
WORKDIR /go/src/app
COPY . .
RUN go get -d -v ./...
RUN CGO_ENABLED=0 GOOS=linux go build -o app .

# Stage 2: Copy the Go binary to an empty Docker image
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /go/src/app/app .
CMD ["./app"]

在这个例子中,首先定义了一个名为builder的构建阶段,它从golang:1.14.2镜像开始,将源代码复制到镜像中,然后编译Go应用程序。

然后,开始第二个构建阶段,它从较小的alpine:latest镜像开始,并从builder阶段复制编译好的Go应用程序到新镜像中。

这样,最终得到的镜像中只包含了编译好的Go应用程序,而没有包含用于编译的Go编译器等额外的工具和依赖,使得镜像更加轻量化。

CMD和ENTRYPOINT有什么区别

CMD 设置默认的被容器执行的命令,并且可以有参数。如果 Docker 运行时(也就是docker run命令)指定了其他命令,CMD 命令会被忽略。

ENTRYPOINT 配置容器启动时运行的命令,让容器以应用程序或服务的形式运行。不同于 CMD,它不会被 docker run 的命令行参数覆盖

也正是这个原因,一般来说,推荐使用ENTRYPOINT, 把所有需要的执行的命令都写进一个脚本,这样可以减少上线过程中的由于传参导致的问题。

如何获取一个docker image的SHA256

代码语言:javascript
代码运行次数:0
复制
docker inspect --format='{{index .RepoDigests 0}}' <docker image> | cut -d ':' -f 2

Docker Compose

Docker Compose 是一款用于定义和运行多容器 Docker 应用程序的工具,它允许用户通过一个 YAML 文件(通常名为 docker-compose.yml)来配置整个应用的容器服务、网络、数据卷以及其他相关设置。Docker Compose 是 Docker 官方提供的编排工具,主要用于简化在单台机器上运行多个 Docker 容器的过程。

从我的实际工作经验来看,docker compose最大的好处有两个:依赖管理和环境切换。 Docker Compose 可以管理服务间的依赖关系,确保服务按照正确的顺序启动和停止。 也可以为不同的环境(如开发、测试、生产)编写不同的 docker-compose.yml 文件,并通过 -f 参数指定加载不同的配置文件。

下面是一个案例和讲解。

代码语言:javascript
代码运行次数:0
复制
version: '3.9'

services:
  db:
    image: postgres:13-alpine
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: example
    volumes:
      - db_data:/var/lib/postgresql/data

  backend:
    build: ./backend
    depends_on:
      - db
    environment:
      DB_HOST: db
      DB_PORT: 5432
      DB_USER: myuser
      DB_PASS: example

  frontend:
    build: ./frontend
    ports:
      - "80:80"
    depends_on:
      - backend

volumes:
  db_data:

networks:
  default:
    name: my_app_net

在这个例子中:

  • 有一个名为 db 的服务,它是基于 Postgres 数据库镜像的容器。
  • backend 服务依赖于 db 服务,意味着 backend 服务会在 db 服务启动并准备就绪后再启动。depends_on 关键字用于表达这种依赖关系。
  • backend 服务需要连接到 db 服务,所以它设置了 DB_HOSTdb,这是因为在同一个 Docker Compose 网络中,服务可以通过服务名进行互相访问。
  • frontend 服务同样依赖于 backend 服务,只有当 backend 完全启动后才会启动 frontend 服务。
  • volumes 部分定义了一个持久化的数据卷 db_data,用于存储 db 服务的数据,确保数据在容器重启时不丢失。
  • 最后,所有的服务都被分配到了默认网络 my_app_net 中,以便它们之间能够相互通信。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • COPY 和 ADD 命令的区别
  • 多阶段构建
  • CMD和ENTRYPOINT有什么区别
  • 如何获取一个docker image的SHA256
  • Docker Compose
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档