I have a file on the root of my project, and I am opening it like this:
file, err := os.Open("file.csv")
When I make go run main.go it works. When I use the dockerfile to run the app it doesn't work:
open fiile.csv: no such file or directory
My dockerfile is like this:
FROM golang:alpine as builder
RUN mkdir /build
ADD . /build/
WORKDIR /build
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main .
FROM scratch
COPY --from=builder /build/main /app/
WORKDIR /app
CMD ["./main"]
I am not used to dockerfiles so any improv is welcome too!
In the line COPY --from=builder /build/main /app/ you only copy the executable. You do not copy the app directory. Replace that line with COPY --from=builder /build /app/
Below I have included an example of how I would write this Dockerfile. Here are some key changes.
Define WORKDIR before COPY instructions so you do not have write directory names twice. This is helpful because if you want to change your app directory, you only need to change it once (and that means smaller chance of bugs).
Use COPY instead of ADD. The Dockerfile reference indicates that COPY is preferred.
You do not have to use RUN mkdir /build before using a WORKDIR or COPY. Those last two instructions will make the directory if it does not exist already.
FROM golang:alpine as builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main .
FROM scratch
WORKDIR /app
COPY --from=builder /build .
CMD ["./main"]
Related
I have built a Golang image using alpine, my code has functions that need to convert videos using ffmpeg.
My problem is when I try to run ffmpeg on a scratch image, I try to copy the binaries but it doesn't work when my code tries to run ffmpeg.
FROM mwader/static-ffmpeg:5.1 as FFmpeg
FROM golang:alpine AS builder
# Add dependencies
RUN apk add git
RUN apk --no-cache add tzdata
RUN apk add --no-cache ffmpeg
# Set necessary environmet variables needed for our image
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# Move to working directory /build
WORKDIR /build
# Copy and download dependency using go mod
COPY go.mod .
COPY go.sum .
RUN go mod download
# Copy the code into the container
COPY . .
# Build the application
RUN go build -o main .
# Move to /dist directory as the place for resulting binary folder
WORKDIR /dist
# Copy binary from build to main folder
RUN cp /build/main .
RUN cp /build/dev.env .
# Build a small image
FROM scratch
#Copy from builder bin
COPY --from=builder /dist/main /
COPY --from=builder /build/dev.env .
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=FFmpeg /ffmpeg /usr/local/bin/
COPY --from=FFmpeg /ffprobe /usr/local/bin/
#Set Timezone
ENV TZ="America/Montevideo"
# Copy certificates
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Expose port out container
EXPOSE 8080
# Command to run
CMD ["/main"]
I expect run ffmpeg into scratch image.
Trying to build a docker image with golang and react code. The environment variable JWT_SECRET_KEY is not being set.
# Build the Go API
FROM golang:latest AS builder
ADD . /app
WORKDIR /app/server
ENV JWT_SECRET_KEY=DefaultKey
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-w" -a -o /main .
# Build the React application
FROM node:alpine AS node_builder
COPY --from=builder /app/client ./
RUN npm install
RUN npm run build
# Final stage build, this will be the container
# that we will deploy to production
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /main ./
COPY --from=node_builder /build ./web
RUN chmod +x ./main
EXPOSE 8080
CMD ./main
To build this i ran the command
docker build -t webapp .
If you want JWT_SECRET_KEY to be set in the production stage you need to move it to that stage. Or if you need it in both copy it. So change your docker file to
# Build the Go API
FROM golang:latest AS builder
ADD . /app
WORKDIR /app/server
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-w" -a -o /main .
# Build the React application
FROM node:alpine AS node_builder
COPY --from=builder /app/client ./
RUN npm install
RUN npm run build
# Final stage build, this will be the container
# that we will deploy to production
FROM alpine:latest
RUN apk --no-cache add ca-certificates
ENV JWT_SECRET_KEY=DefaultKey
COPY --from=builder /main ./
COPY --from=node_builder /build ./web
RUN chmod +x ./main
EXPOSE 8080
CMD ./main
This is my Dockerfile
FROM golang:1.13 as builder
WORKDIR /app
COPY invoke.go ./
COPY readproperties.go ./
COPY config.properties ./
RUN CGO_ENABLED=0 GOOS=linux go build -v -o server
FROM fishtownanalytics/dbt:0.19.0
USER root
WORKDIR /dbt
COPY --from=builder /app/server ./
COPY script.sh ./
COPY jaffle-shop ./
ENTRYPOINT ["./server"]
When I run the Docker image and the Go server (invoke.go has the main which calls readproperties function) references the config.properties, I get the following error:
2021/04/21 22:27:29 Go: starting server...
2021/04/21 22:27:29 open config.properties: no such file or directory
How do I copy the properties file ?
It has key=value pairs
Building and running this way:
docker build -t sample:v1
PORT=8080 && docker run -p 9090:${PORT} -e PORT=${PORT} sample:v1
All the files are in the same location as the Dockerfile.
Your properties file is copied to the "builder" stage - where it is not needed during compilation. Instead it should be copied to the final stage.
Update your Dockerfile to:
FROM golang:1.13 as builder
WORKDIR /app
COPY invoke.go ./
COPY readproperties.go ./
#
# REMOVE:
#
# COPY config.properties ./
RUN CGO_ENABLED=0 GOOS=linux go build -v -o server
FROM fishtownanalytics/dbt:0.19.0
USER root
WORKDIR /dbt
COPY --from=builder /app/server ./
COPY script.sh ./
COPY jaffle-shop ./
#
# ADD:
#
COPY config.properties ./
#
# OR: copy it from the builder stage
#
#COPY --from=builder /app/config.properties ./
ENTRYPOINT ["./server"]
I have a container with Golang that calls a https api. I'm using a scratch container and when I try to run I get a certificate signed by unknown authority
url := "https://restcountries.eu/rest/v2/name/" + params.Get("country")
response, err := http.Get(url)
My Dockerfile is like this:
FROM golang:1.15 AS builder
WORKDIR /GreetingAPI
COPY . /greeting
WORKDIR /greeting
ENV GO111MODULE=on
RUN CGO_ENABLED=0 GOOS=linux go build -o greeting
FROM scratch
COPY --from=builder /greeting .
CMD ["./greeting"]
I updated my Dockerfile using this answare. But when I try to build the container I get ERROR: "/ca-certificates.crt" not found: not found and failed to solve: rpc error: code = Unknown desc = failed to compute cache key: "/ca-certificates.crt" not found: not found
FROM golang:1.15 AS builder
WORKDIR /GreetingAPI
COPY . /greeting
WORKDIR /greeting
ENV GO111MODULE=on
RUN CGO_ENABLED=0 GOOS=linux go build -o greeting
FROM scratch
ADD ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /greeting .
CMD ["./greeting"]
I may have needed to be more clear in the linked answer, the copy in this first example was a single stage example where you had a certificate file to inject in your build context (directory that typically has your Dockerfile):
FROM scratch
ADD ca-certificates.crt /etc/ssl/certs/
ADD main /
CMD ["/main"]
You have a multi-stage build and can follow the multi-stage method in the second half of the linked answer. That installs the certificates in another stage from the distribution vendor and copies them into your scratch stage:
FROM golang:alpine as build
RUN apk --no-cache add ca-certificates
WORKDIR /go/src/app
COPY . .
RUN CGO_ENABLED=0 go-wrapper install -ldflags '-extldflags "-static"'
FROM scratch
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /go/bin/app /app
ENTRYPOINT ["/app"]
However, that second example assumed Alpine as the base for the first stage, using apk. (It also assumed the certificates need to be installed in the base image, which turns out to not be the case in the current golang images.) For your example, it's based on Debian in the golang:1.15 image. For that, you'd normally need apt-get commands, but in this case the ca-certificates package is already installed, so you can just copy the results:
FROM golang:1.15 AS builder
COPY . /greeting
WORKDIR /greeting
ENV GO111MODULE=on
RUN CGO_ENABLED=0 GOOS=linux go build -o greeting
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /greeting /
CMD ["/greeting"]
Install ca cert in your builder stage and copy over to the final image. Something like:
FROM golang:1.15 AS builder
RUN apk update
RUN apk add -U --no-cache ca-certificates && update-ca-certificates
WORKDIR /GreetingAPI
COPY . /greeting
WORKDIR /greeting
ENV GO111MODULE=on
RUN CGO_ENABLED=0 GOOS=linux go build -o greeting
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /greeting .
CMD ["./greeting"]
When I was trying to build golang using docker
The image build of docker was successful, but the following error occurred when running with docker run
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"/app\": permission denied": unknown.
I think this error cause no user add, so I added group and user as below
RUN groupadd -g 10001 myapp \
&& useradd -u 10001 -g myapp myapp
but didn't fix.
Here is my source docker file
FROM golang:1.12.9 as builder
ADD . /go/src/appname/
WORKDIR /go/src/appname/
ENV GO111MODULE=on
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 make build target=prod
FROM alpine
RUN apk update \
&& apk add --no-cache
COPY --from=builder /go/src/ /app
ENTRYPOINT [ "/app" ]
thanks
You are copying your entire source folder into the directory /app in this step:
COPY --from=builder /go/src/ /app
Then you try to execute the directory:
ENTRYPOINT [ "/app" ]
Instead, you need to copy the compiled binary that your go build outputs in the copy step.
You need to specify the output directory to your binary.
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o /app .
then copy the app directory
COPY --from=builder /app ./
RUN chmod +x ./app
ENTRYPOINT ["./app"]
Thanks to the advice of everyone, I fix this issue
I couldn't just COPY with the build binary properly specified
before
COPY --from=builder /go/src/ /app
after
COPY --from=builder /go/src/build/build_app_name /app
thanks!!