首页 > 解决方案 > 使用 nginx 作为基础镜像的 Packer Docker 构建器

问题描述

期待

Here is my packer file:

{
        "builders" : [
        {
                "type": "docker",
                "image": "nginx",
                "commit": "true"
        }
        ],
        "provisioners" : [
        {
                "type": "file",
                "source": "./index.html",
                "destination": "/usr/share/nginx/html/index.html"
        }
        ],
        "post-processors" : [
        {
                "type": "docker-tag",
                "repository": "repo",
                "tag": "latest"
        }
        ]
}

在为上述文件运行 docker 容器时构建上述文件后,使用命令docker run -it -d -p 8080:80 --name web repo自定义 nginx docker 映像,观察到 docker 容器出现,端口已被占用,但 nginx 进程未在 docker 容器内运行,因为无法在指定端口上访问 html 内容。网址:http://localhost:8080

然而,上面创建自定义 nginx docker 镜像和运行 docker 容器的场景是使用下面的 Dockerfile 和 docker 命令执行的,它工作正常,即 docker 容器出现,端口被占用并且 HTML 内容也可以访问:

这是 Dockerfile:

FROM nginx:latest
COPY ./index.html /usr/share/nginx/html/index.html

我需要使用 packer docker builder,可能会出现什么问题?将 docker builder 与 packer 或 nginx 一起使用是否有任何限制?

标签: dockernginxpacker

解决方案


问题是加壳程序在其所有荣耀中都会覆盖入口点。Packer 通过“执行”到正在运行的容器中并提交它来工作。所以它实际上并不使用 docker 构建系统。

当您提交容器时,图像将获取容器启动的入口点和 cmd,如果是打包程序,它会/bin/sh默认将入口点设置为。

一种选择是不让它改变入口点。我已从--entrypoint默认命令中删除。

source "docker" "nginx" {
  image  = "nginx"
  commit = true
  run_command = ["-d", "-i", "-t", "--", "{{.Image}}"]
}

但是,我不确定这是否总是有效。我认为 nginx 入口点很特别,因为它只会在最后执行参数,如果 nginx 不是第一个参数,它什么也不做。

exec "$@"

也许有时您需要给它一个 shell 入口点,以便让打包程序在映像中正常工作。然后,恢复更改数组中的 cmd 和入口点。奇怪的是,当我这样做时,我需要恢复CMD它,否则它将是null.

source "docker" "nginx" {
  image  = "nginx"
  commit = true
  changes = [
    "ENTRYPOINT [\"/docker-entrypoint.sh\"]",
    "CMD [\"nginx\", \"-g\", \"daemon off;\"]"
  ]
}

这是一个完整的工作示例

packer {
  required_plugins {
    docker = {
      version = ">= 1"
      source  = "github.com/hashicorp/docker"
    }
  }
}
source "docker" "nginx" {
  image  = "nginx"
  commit = true
  # either don't overwrite the entrypoint
  run_command = ["-d", "-i", "-t", "--", "{{.Image}}"]
  # or restore it
  changes = [
    "ENTRYPOINT [\"/docker-entrypoint.sh\"]",
    "CMD [\"nginx\", \"-g\", \"daemon off;\"]"
  ]
}
build {
  sources = [
    "source.docker.nginx",
  ]
  provisioner "file" {
    source = "./index.html"
    destination = "/usr/share/nginx/html/index.html"
  }
  post-processor "docker-tag" {
    repository = "web"
  }
}

推荐阅读