dockergodockerfile

How do I add two files in the Dockerfile for my Golang web server?


I'm currently setting up an HTTPS server with Go using a self-signed signature stored in cert.pem and key.pem for development. Whenever I run the server locally, it works just fine, allowing me to connect to my HTTPS server. However, when I build my Dockerfile and run it from there, my browser returns this page:

enter image description here

I keep trying to use ADD and COPY with the two files in my Dockerfile because I'm not sure if it's being included in my Go project after it's built, but whenever I try to build the modified Dockerfile, it gives me an error that says that it can't find the files. The docker command I'm running is sudo docker run -p 8080:8080 hxgo-skeleton. How do I add the cert.pem and key.pem files into my Dockerfile for a Golang web server?

Dockerfile

# Build
FROM golang:1.23.3-alpine AS build-env
ENV APP_NAME=hxgo-skeleton
ENV CMD_PATH=cmd/api/main.go
COPY . $GOPATH/src/$APP_NAME
COPY .env $GOPATH/src/$APP_NAME
WORKDIR $GOPATH/src/$APP_NAME

# Building the Go application
RUN CGO_ENABLED=0 go build -v -o /$APP_NAME $GOPATH/src/$APP_NAME/$CMD_PATH
 
# Run
FROM alpine:3.14
ENV APP_NAME=hxgo-skeleton
COPY --from=build-env /$APP_NAME .
COPY .env .
EXPOSE 8080
CMD ./$APP_NAME


Solution

  • You should inject the TLS certificate and private key using a Docker bind mount when you run the container.

    docker run \
      -v "$PWD/certs:/certs" \  # <-- add
      -p 8080:8080 \
      hxgo-skeleton
    

    The first path in the -v option is the directory on your local system where the TLS certificate data lives, and the second path is the path in the container filesystem where your application expects to find it. If you're running this via Docker Compose, its volumes: has similar syntax except that it understands relative paths on the left-hand side.

    Do not try to embed the TLS certificate directly in the image. There are two good reasons for this. As a practical matter, the TLS certificate is tied to a specific DNS name, so you'd have to rebuild the image for each new deployment, and you typically would prefer images that would be reused in any environment. From a security point of view, it's very easy to copy files back out of a container, and so anyone who has a copy of your image can also steal your private key.


    From a mechanical point of view, in your multi-stage build, after the last FROM line, you're only COPY --from=build the application itself and the .env file. Nothing else will be in the final image. That means your image won't contain the Go toolchain (good) and it won't contain your source code (good) but any other support files that might be in the repository won't be copied. If you needed these and it was appropriate to ship them in the image, you'd need to separately COPY them.