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.
Related
I am having an issue where the docker buildx tool doesn't properly copy files to the production container. For example:
FROM --platform=$BUILDPLATFORM node:16.14.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY yarn.lock ./
RUN apk update && apk add python3 g++ make && rm -rf /var/cache/apk/*
RUN yarn install
COPY . ./
RUN yarn run build
# production environment
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html/
COPY ./nginx/nginx.conf /etc/nginx/conf.d/default.conf
# Default port exposure
EXPOSE 80
# Copy .env file and shell script to container
COPY ./env.sh /usr/share/nginx/html/env.sh
# Start Nginx server
CMD ["/bin/sh", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""]
All of the files from build will copy properly. However, the nginx.conf and env.sh will report as not found. Any ideas?
P.S: This seems to be an issue with nginx:alpine. No clue
This is the recommended Dockerfile from the official documentation
# Install dependencies only when needed
FROM node:alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# Rebuild the source code only when needed
FROM node:alpine AS builder
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN yarn build && yarn install --production --ignore-scripts --prefer-offline
# Production image, copy all the files and run next
FROM node:alpine AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# You only need to copy next.config.js if you are NOT using the default configuration
# COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
USER nextjs
EXPOSE 3000
ENV PORT 3000
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry.
# ENV NEXT_TELEMETRY_DISABLED 1
CMD ["node_modules/.bin/next", "start"]
It takes about 8min to build right now, it was 6 plus something at the beginning.
I'm deploying it into GCP using a Cloud Build pipeline which trigger is a push to a given branch and just wondering the reason to add three different runs of node:alpine.
At the end it will be triggered anytime some push happen in the given branch so it will need to re-create everything.
Shouldn't something like this work better for those building it outside Vercel or similar?
FROM node:14.17-alpine AS deps
RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app
ENV NODE_ENV production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY package.json ./
RUN yarn build && yarn install --production
COPY /app/next.config.js ./
COPY /app/public ./public
COPY --chown=nextjs:nodejs /app/.next ./.next
COPY /app/node_modules ./node_modules
COPY /app/package.json ./package.json
RUN npx next telemetry disable
USER nextjs
EXPOSE 3000
CMD ["yarn", "start"]
It's not working and I'm trying to make it work like that to see results but in the meantime I would like to get help on figuring out if there's any issue in my mental workaround about that, I'm not an expert on that so I may be missing something.
The reason it's faster is because at the point where you do your yarn build, the only file you've copied into the image is package.json. The original Dockerfile has copied everything, so it can actually build your app.
As for the multi-stage nature of the first Dockerfile, I think its main advantage is that the final image only contains the output of the build. With a single-stage build like the latter file, the image will contain both the source files and the built files.
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"]