通过 kubernetes/skaffold 将私有 npm 存储库拉取到 docker 容器

Ger*_*ito 3 npm docker kubernetes skaffold .npmrc

我是 skaffold、k8s、docker set 的新手,在本地集群上构建应用程序时遇到了问题。

我有一个代码存储库,试图提取私有 NPM 包,但在构建时丢失了 .npmrc 文件或 npm 机密。

npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/@sh1ba%2fcommon - Not found
npm ERR! 404 
npm ERR! 404  '@sh1ba/common@^1.0.3' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404 
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-06-02T06_08_57_246Z-debug.log
unable to stream build output: The command '/bin/sh -c npm install' returned a non-zero code: 1. Please fix the Dockerfile and try again..
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望避免将秘密硬编码到文件中,并使用 k8s 环境变量将密钥作为秘密传递给 docker。我可以(某种程度上)使用 docker build 命令来做到这一点:

  • 与“--build-args”和npm秘密(不安全的方式)
  • 与“--secret”和npm Secret(更好的方法)
  • 直接复制 .npmrc 文件,npm install然后立即删除它

当我尝试使用 kubernetes/skaffold 构建它时,问题就出现了。运行后,似乎没有找到任何 args、env 变量,甚至 .npmrc 文件。在检查 dockerfile 中寻找线索时,我发现没有任何内容从清单(定义的参数、.npmrc 文件等)传递到 dockerfile。

以下是该应用程序的清单:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth-depl
spec:
  replicas: 1
  selector: 
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
    spec:
      containers:
        - name: auth
          image: auth
          env:
            - name: NPM_SECRET
              valueFrom:
                secretKeyRef:
                  name: npm-secret
                  key: NPM_SECRET
          args: ["--no-cache", "--progress=plain", "--secret", "id=npmrc,src=.npmrc"]
Run Code Online (Sandbox Code Playgroud)

这是 dockerfile 中的代码:

# syntax=docker/dockerfile:1.2
# --------------> The build image
FROM node:alpine AS build
WORKDIR /app
COPY package*.json .
RUN --mount=type=secret,mode=0644,id=npmrc,target=/app/.npmrc \
  npm install

# --------------> The production image
FROM node:alpine

WORKDIR /app
COPY package.json .
COPY tsconfig.json .
COPY src .
COPY prisma .

COPY --chown=node:node --from=build /app/node_modules /app/node_modules
COPY --chown=node:node . /app
s
RUN npm run build

CMD ["npm", "start"]
Run Code Online (Sandbox Code Playgroud)

还有 skaffold 文件:

apiVersion: skaffold/v2alpha3
kind: Config
deploy:
  kubectl:
    manifests:
      - ./infra/k8s/*
      - ./infra/k8s-dev/*
build:
  local:
    push: false
  artifacts:
    - image: auth
      context: auth
      docker:
        dockerfile: Dockerfile
      sync:
        manual:
          - src: 'src/**/*.ts'
            dest: .
Run Code Online (Sandbox Code Playgroud)

一些注意事项:

  • 无论我将其复制并粘贴到何处(在 auth 中、在清单中、在 skaffold 中和在 ~/ 目录中),我都无法找到 .npmrc 文件
  • 我也想在生产中使其半可用(相当可重用),这样如果可能的话我不需要进行彻底的检修(但如果这是不好的做法,我想听到更多关于它的信息)
  • 我已经能够使其与 skaffold.yaml 文件中的 buildArgs 一起使用,但我不确定这将如何转化为生产环境,因为我无法将构建参数从 kubernetes 传递到 docker (我读到它不是不安全,应该使用秘密)
  • 清单中的参数也会引发此错误(如果参数被注释掉,服务器就会运行):
 - deployment/auth-depl: container auth terminated with exit code 9
    - pod/auth-depl-85fb8975d8-4rh9r: container auth terminated with exit code 9
      > [auth-depl-85fb8975d8-4rh9r auth] node: bad option: --progress=plain
      > [auth-depl-85fb8975d8-4rh9r auth] node: bad option: --secret
 - deployment/auth-depl failed. Error: container auth terminated with exit code 9.
Run Code Online (Sandbox Code Playgroud)

任何见解都会令人惊奇,我已经摆弄这个太久了。

谢谢你!

Bri*_*wis 11

构建镜像并将其部署到 Kubernetes 分为三个级别:

  1. 您启动映像构建的本地系统
  2. Docker 构建填充镜像,然后将该镜像存储在某处
  3. 加载并开始运行该镜像的 Kubernetes 集群

Docker 不参与#3。 (这只是部分正确,因为一些集群也使用 Docker 来运行容器,但这是一个隐藏的细节,而且也在变化。)

您可以在两个地方传达秘密:

  • 在图像构建时(步骤#1到#2):您可以使用Docker--build-args或安装秘密--secret(两者都需要Buildkit)
  • 在部署时(步骤#3):您使用 Kubernetes 机密或配置映射,它们是与映像构建分开配置的

--build-argsSkaffold 支持使用 Docker和标志传递构建时机密,例如您的 npm 密码--secret,尽管它们稍有重命名。

buildArgs支持 Go 风格的模板,因此您可以引用环境变量,MYSECRET例如{{.MYSECRET}}

build:
  local:
    useBuildkit: true
  artifacts:
    - image: auth
      context: auth
      docker:
        buildArgs:
          MYSECRET: "{{.MYSECRET}}"
Run Code Online (Sandbox Code Playgroud)

然后您可以MYSECRET在您的Dockerfile

ARG MYSECRET
RUN echo MYSECRET=${MYSECRET}
Run Code Online (Sandbox Code Playgroud)

请注意,除非您通过ENV MYSECRET=${MYSECRET}.

如果秘密位于本地文件中,您可以使用secret以下字段skaffold.yaml

build:
  local:
    useBuildkit: true
  artifacts:
    - image: auth
      context: auth
      docker:
        secret:
          id:   npmrc
          src: /path/to/.npmrc
Run Code Online (Sandbox Code Playgroud)

然后您将在以下内容中引用该秘密Dockerfile

RUN --mount=type=secret,mode=0644,id=npmrc,target=/app/.npmrc \
  npm install
Run Code Online (Sandbox Code Playgroud)

现在在您的 中Deployment,您尝试args为容器进行设置:

          args: ["--no-cache", "--progress=plain", "--secret", "id=npmrc,src=.npmrc"]
Run Code Online (Sandbox Code Playgroud)

args字段会覆盖CMD图像中设置的指令。该字段用于提供提供给图像入口点的命令行参数,这可能是node. 如果您想引用集群上正在运行的容器中的机密,您可以使用SecretConfigMap