Reputation: 81
I am new to skaffold, k8s, docker set and I've been having trouble building my application on a cluster locally.
I have a code repository that is trying to pull a private NPM package but when building it loses the .npmrc file or the npm secret.
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..
Ideally I'd like to avoid hard coding the secret into the file and use a k8s environment variable to pass in the key to docker as a secret. I am able to (kind of) do it with the docker build command:
npm install
ing and deleting it right afterThe issue arises when I try to build it using kubernetes/skaffold. After running, it doesn't seem like any of the args, env variables, or even the .npmrc file is found. When checking in the dockerfile for clues I was able to identify that nothing was being passed over from the manifest (args defined, .npmrc file, etc) to the dockerfile.
Below is the manifest for the application:
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"]
Here's the code in the 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"]
And also the skaffold file:
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: .
A few notes:
- 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.
Any insight would be amazing, I've been fiddling with this for far too long now.
Thank you!
Upvotes: 3
Views: 3698
Reputation: 2974
Building and deploying an image to Kubernetes is at three levels:
Docker is not involved in #3. (This is only partially true, since some clusters use Docker to run the containers too, but that's a hidden detail and is also changing.)
There are two places where you might communicate secrets:
--build-args
or mounting secrets with --secret
(both require Buildkit)Skaffold supports passing build-time secrets, like your npm password, with Docker's --build-args
and --secret
flags, though they are slightly renamed.
buildArgs
supports Go-style templating, so you can reference environment variables like MYSECRET
as {{.MYSECRET}}
:
build:
local:
useBuildkit: true
artifacts:
- image: auth
context: auth
docker:
buildArgs:
MYSECRET: "{{.MYSECRET}}"
Then you can reference MYSECRET
within your Dockerfile
:
ARG MYSECRET
RUN echo MYSECRET=${MYSECRET}
Note that build-args are not propagated into your container unless you explicitly assign it via an ENV MYSECRET=${MYSECRET}
.
If the secret is in a local file, you can use the secret
field in the skaffold.yaml
:
build:
local:
useBuildkit: true
artifacts:
- image: auth
context: auth
docker:
secret:
id: npmrc
src: /path/to/.npmrc
and you'd then reference the secret as you are in your Dockerfile
:
RUN --mount=type=secret,mode=0644,id=npmrc,target=/app/.npmrc \
npm install
Now in your Deployment
, you're attempting to setting args
for your container:
args: ["--no-cache", "--progress=plain", "--secret", "id=npmrc,src=.npmrc"]
The args
field overrides the CMD
directive set in your image. This field is used to provide command-line arguments provided to your image's entrypoint, which is likely node
. If you want to reference a secret in a running container on a cluster, you'd use a Secret
or ConfigMap
.
Upvotes: 11