Shell命令未识别变量:证书写入容器及COPY报错求助
Let's walk through what's wrong with both of your approaches, then fix them and share alternative ways to get your certificate into the container.
Issue 1: The RUN Command with Variable Assignment
Your first error /bin/sh: CERT: not found is a classic shell syntax mistake: you can't have spaces around the equals sign when assigning variables in shell. When you write CERTS = $(...), the shell interprets CERTS as a command to run, hence the "not found" error.
There are two other small issues here too:
- The
opensslcommand is throwing verification warnings (thoseverify error:num=20lines) — these are non-fatal, but they clutter the build output. We can redirect them to/dev/null. - Using
echo $CERTSwithout quotes will collapse all newlines in the certificate into spaces, which will break the certificate format. You need double quotes to preserve line breaks.
Fixed RUN Command
# Combine commands to reduce image layers, fix variable syntax, and preserve certificate format RUN apk add --no-cache ca-certificates openssl && \ CERTS=$(echo -n | openssl s_client -connect keycloak.abc.domain.com:443 -servername keycloak.abc.domain.com -showcerts 2>/dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p') && \ echo "$CERTS" > /usr/local/share/ca-certificates/mycert.crt && \ update-ca-certificates
I added -servername keycloak.abc.domain.com to the openssl command — this is critical for servers using SNI (most modern HTTPS servers do), otherwise you might get the wrong certificate or no certificate at all.
Issue 2: COPYing a Local Certificate
The error COPY failed: stat /var/lib/docker/tmp/docker-builder950940816/mycert.crt: no such file or directory means Docker can't find your certificate file in the build context.
Docker uses the directory you run docker build from as the build context — all COPY paths are relative to this directory. So if you run docker build from ~/my-project, your mycert.crt needs to be in ~/my-project (or a subdirectory within it). You can't COPY files from outside the build context by default (for security reasons).
Fixed COPY Approach
- Move your
mycert.crtinto the same directory as your Dockerfile (or a subdirectory like./certs). - Update your Dockerfile:
RUN apk add --no-cache ca-certificates COPY mycert.crt /usr/local/share/ca-certificates/ RUN update-ca-certificates
If your cert is in a subdirectory:
COPY certs/mycert.crt /usr/local/share/ca-certificates/
Alternative: Pass Certificate Content via Build Argument
If you don't want to check the certificate into your repo or fetch it during the build, you can pass the certificate content directly as a build argument:
Dockerfile
ARG CERT_CONTENT RUN apk add --no-cache ca-certificates && \ echo "$CERT_CONTENT" > /usr/local/share/ca-certificates/mycert.crt && \ update-ca-certificates
Build Command
docker build --build-arg CERT_CONTENT="$(cat /path/to/your/mycert.crt)" .
This way, you don't need to include the certificate in your build context at all.
内容的提问来源于stack exchange,提问作者Liza

