I'm using the build docker image from golang:alpine.
My purpose is just to copy the executed binary file to a new scratch image.
Below its my Dockerfile:
############################
# STEP 1 build executable binary
############################
FROM golang#sha256:d481168873b7516b9f34d322615d589fafb166ff5fd57d93e96f64787a58887c AS builder
RUN apk update && apk add --no-cache git tzdata ca-certificates && update-ca-certificates
ADD . $GOPATH/src/piggybank2go
WORKDIR $GOPATH/src/piggybank2go
COPY . .
# Fetch dependencies.
RUN go get -u github.com/golang/dep/cmd/dep
RUN dep ensure -v
# Build executeable binary
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o $GOPATH/bin/piggybank2go
# RUN go build -o /go/bin/piggybank2go
############################
# STEP 2 build a small image
############################
FROM scratch
# Copy our static executable
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder $GOPATH/bin/piggybank2go $GOPATH/bin/piggybank2go
# Port on which the service will be exposed.
EXPOSE 8081
ENTRYPOINT ["$GOPATH/bin/piggybank2go"]
But I got this error:
Step 12/14 : COPY --from=builder $GOPATH/bin/piggybank2go $GOPATH/bin/piggybank2go
COPY failed: stat /var/lib/docker/overlay2/b37bbe725b51ba50e3082d162e75d4cdee368499e26887c6921486415c089920/merged/bin/piggybank2go: no such file or directory
I think the problem is that the environment variable $GOPATH only exists in the golang image and not the scratch image. So try change the COPY-line to:
COPY --from=builder /go/bin/piggybank2go /go/bin/piggybank2go
Environment variables from the first stage are not available in the second stage. For this reason "$GOPATH" cannot be resolved correctly in the second stage, hence the error.
In the second stage you should know exactly what and to where you are copying:
COPY --from=builder /go/bin/piggybank2go /go/bin/piggybank2go
Related
I have a problem implementing sharp for Dockerfile.
Error: 'sharp' is required to be installed in standalone mode for the image
optimization to function correctly
Next.js with sharp works fine for local developing:
next 12.0.1
sharp 0.30.2
node 16.xx
npm 8.xx
OS - macOS Monterey - 12.2.1, M1 PRO
next.config.js
module.exports = {
experimental: {
outputStandalone: true,
},
}
Dockerfile:
FROM node:16-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 package-lock.json ./
RUN npm ci
# Rebuild the source code only when needed
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 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 during the build.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build
# Production image, copy all the files and run next
FROM node:16-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# You only need to copy next.config.js if you are NOT using the default configuration
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/next-i18next.config.js ./
COPY --from=builder /app/next-sitemap.js ./cd
COPY --from=builder /app/jsconfig.json ./jsconfig.json
COPY --from=builder /app/data/ ./data
COPY --from=builder /app/components/ ./components
COPY --from=builder /app/utils/ ./utils
COPY --from=builder /app/assets/ ./assets
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
.env file:
NEXT_SHARP_PATH=/tmp/node_modules/sharp next start
Sharp is installed in package.json
I checked both Next/Vercel tuts:
https://nextjs.org/docs/messages/install-sharp
https://nextjs.org/docs/messages/sharp-missing-in-production
RUN Docker:
docker build --no-cache . -t website-app && docker run --name website -p 3000:3000 website-app
I figured it out.
I removed NEXT_SHARP_PATH=/tmp/node_modules/sharp next start from .env
Local docker doesn't work with node-sharp without NEXT_SHARP_PATH and that is weird.
But I deployed it in my K8s Cluster with Docker and it works as is expected.
npm i sharp
this fix the problem for me
What works for me, is to change the version of Alpine Linux in the Dockerfile:
FROM node:18-alpine AS deps (instead of node:16)
Adding or removing node-sharp in my .env file didn't work for me.
For the final step (the one labeled "runner") in your Dockerfile, replace the base image with node:16-slim. This image is Debian-based, so it is approximately 20 MB larger than the alpine variant, but it has the binaries required to run sharp.
When using a similar Dockerfile to yours, I found that the NEXT_SHARP_PATH environment variable was not needed when using a Debian-based Node image.
And for reference, here is the NextJS documentation about the error message: https://nextjs.org/docs/messages/sharp-missing-in-production
Update: You may also be able to specify the libc implementation found in your base Docker image by using the following flags:
RUN npm_config_platform=linux npm_config_arch=x64 npm_config_libc=glibc npm ci
For more information about what these flags are, see the documentation for sharp.
I have the following dockerfile:
FROM golang:1.16.3 as compile
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# CGO_ENABLED for static linking library
RUN go env -w GOPRIVATE="github.com/<some_account>/*"; GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X main.version=$1 -X main.build=`date -u +%Y%m%d.%H%M%S`" -o /app/server server.go
FROM scratch
#WORKDIR /
#FROM alpine:latest
#RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=compile /app/server .
EXPOSE 80
EXPOSE 443
CMD ["./server"]
This file is located with my Golang source codes and I run docker build . to build the executable as a docker image. But this code uses Go package from a private repo in GitHub. And during the first stage, it cannot access that private repo. In my RUN statement I attempt to set the Go Environment GOPRIVATE, but it doesn't work.
ARG GOPRIVATE "github.com/<some_account>/*" and ENV GOPRIVATE "github.com/<some_account>/*" also seem to have no effect.
You need to give your build env access to the private repo. In your pre-stage Docker build, generate a.netrc file with an access token to your private repo:
# .netrc
## generate token with https://help.github.com/articles/creating-an-oauth-token-for-command-line-usee
machine github.com login <token>
This should resolve your build issue.
I’ve the following docker which works ok, I was able to run it and build it successfully!
FROM golang:1.13.6 AS build-env
ENV GO111MODULE=on
ENV GOOS=linux
ENV CGO_ENABLED=0
RUN mkdir -p /go/src/github.company.corp/deng/fst-cl
WORKDIR /go/src/github.company.corp/deng/fsr-clie
COPY ./ ./
# build the code
RUN go build -v -o ./fsr ./src/cmd/main.go
Now I want to change the image to use lighter docker image such as go alpine
So I change the from and added alpine version and also added git ,however the build is failing for
So go lib which doesn’t happen before the change, any idea what could be missing ?
FROM golang:1.13.6-alpine AS build-env
ENV GO111MODULE=on
ENV GOOS=linux
ENV CGO_ENABLED=0
## git is required to fetch go dependencies
RUN apk add --no-cache ca-certificates git
RUN apk add --no-cache gcc musl-dev
RUN mkdir -p /go/src/github.company.corp/deng/fst-cl
WORKDIR /go/src/github.company.corp/deng/fsr-clie
COPY ./ ./
# build the code
RUN go build -v -o ./fsr ./src/cmd/main.go
The error is for specifid repo which resides on our company git repo, but I don’t understand why its happen on golang:1.13.6-alpine and works ok on golang:1.13.6 ????
Btw I try to use different version of go alpine without success…
This is the error:
get "github.company.corp/deng/logger-ut": found meta tag get.metaImport{Prefix:"github.company.corp/deng/logger-ut", VCS:"git", RepoRoot:"https://github.company.corp/deng/logger-ut.git"} at //github.company.corp/deng/logger-ut?go-get=1
go: github.company.corp/deng/logger-ut#v1.0.0: reading github.company.corp/deng/logger-ut/go.mod at revision v1.0.0: unknown revision v1.0.0
If you want a lighter image and wish to use apline, you can use example below. Your final app image should be something like 7MB on scratch. Adjust it as it fits!
# STAGE 1: prepare
FROM golang:1.13.1-alpine3.10 as prepare
WORKDIR /source
COPY go.mod .
COPY go.sum .
RUN go mod download
# STAGE 2: build
FROM prepare AS build
COPY . .
RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o bin/app -v your/app.go
# STAGE 3: run
FROM scratch as run
COPY --from=build /source/bin/app /app
ENTRYPOINT ["/app"]
I want to use the multi stage build for my gaoling project, when I build the project locally for linux/windows/Mac
I got 12.6 mb of size , I’ve currently small gaoling CLI program.
Now I want to build it with to build from it lightwhigt docker image with the scratch option and build as
I use the following, but when I check the image, I see that the size it 366MB , any idea what am I missing here?
It should be less then 20MB…
#build stage
FROM golang:alpine as builder
WORKDIR /go/src/tzf
ADD . /go/src/tzf
RUN CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -o ova tzf
RUN apk add --no-cache git
FROM golang:alpine
RUN mkdir /build
ADD . /build/
WORKDIR /build
RUN CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -o ova tzf
FROM scratch
COPY --from=builder /build/main /app/
WORKDIR /app
CMD [“./ova -v"]
You should use first a golang:alpine container to build the app, then an alpineto run the compiled app.
Something like this:
# builder
FROM golang:alpine AS builder
WORKDIR /go/src/tzf
ADD . /go/src/tzf
RUN CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -o ova tzf
# runner
FROM alpine
WORKDIR /app
COPY --from=builder /build/main /app/
CMD [“./ova -v"]
should result in a small footprint container.
When you build your final image, be careful to copy only the exact files you want to end up in the image. It makes sense here to make your binary be the ENTRYPOINT of the image, since there's literally nothing else you can do with it.
I might make a two-stage pipeline like so:
# size of this stage doesn't matter; use the standard image
FROM golang AS builder
WORKDIR /go/src/tzf
ADD . ./
RUN CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -o /ova tzf
FROM scratch
# only copy the one file, may as well put it in /
COPY --from=builder /ova /ova
ENTRYPOINT ["/ova"]
# if you want to launch it with default options, you can
# CMD ["-v"]
I'm trying to convert my project to use multi-stage builds. However, the final step always fails with an error:
Step 11/13 : COPY --from=build /bin/grafana-server /bin/grafana-server
COPY failed: stat /var/lib/docker/overlay2/xxxx/merged/bin/grafana-server: no such file or directory
My Dockerfile looks like this:
FROM golang:latest AS build
ENV SRC_DIR=/go/src/github.com/grafana/grafana/
ENV GIT_SSL_NO_VERIFY=1
COPY . $SRC_DIR
WORKDIR $SRC_DIR
# Building of Grafana
RUN \
npm run build && \
go run build.go setup && \
go run build.go build
# Create final stage containing only required artifacts
FROM scratch
COPY --from=build /bin/grafana-server /bin/grafana-server
EXPOSE 3001
CMD ["./bin/grafana-server"]
The build.go build step will output artifacts to ./bin/ -- The error is pretty unhelpful other than telling me the files don't exist where I think they should exist.
My folder structure on my machine is:
--| ~/Documents/dev/grafana/src/grafana/grafana
--------| bin
------------| <grafan-server builds to here>
--------| deploy
------------| docker
----------------| Dockerfile
From ~/Documents/dev/grafana/src/grafana/grafana is where I issue: docker build -t grafana -f deploy/docker/Dockerfile .
To follow-up my comment, the path you set with the WORKDIR is absolute and should be specified in the same way in the COPY --from=build command.
So this could lead to the following Dockerfile:
FROM golang:latest AS build
ENV SRC_DIR=/go/src/github.com/grafana/grafana/
ENV GIT_SSL_NO_VERIFY=1
COPY . $SRC_DIR
WORKDIR $SRC_DIR
# Building of Grafana
RUN \
npm run build && \
go run build.go setup && \
go run build.go build
# Create final stage containing only required artifacts
FROM scratch
ENV SRC_DIR=/go/src/github.com/grafana/grafana/
WORKDIR $SRC_DIR
COPY --from=build ${SRC_DIR}/bin/grafana-server ${SRC_DIR}/bin/grafana-server
EXPOSE 3001
CMD ["./bin/grafana-server"]
(only partially tested)