Docker for golang application - docker

i've golang application which I want to build docker image for it
the application folder called cloud-native-go and the dockerfile is under the root project
Any idea what is wrong here ?
FROM golang:alpine3.7
WORKDIR /go/src/app
COPY . .
RUN apk add --no-cache git
RUN go-wrapper download # "go get -d -v ./..."
RUN go-wrapper install # "go install -v ./..."
#final stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /go/bin/app /app
ENTRYPOINT ./app
LABEL Name=cloud-native-go Version=0.0.1
EXPOSE 3000
The error is :
Step 5/12 : RUN go-wrapper download # "go get -d -v ./..."
---> Running in 70c2e00f332d
/bin/sh: go-wrapper: not found
i Build it with
docker build -t cloud-native-go:1.0.0 .

go-wrapper has been deprecated and removed from the images using go version 10 and above. See here.
If you are fine using go v1.9 you can use the following image: golang:1.9.6-alpine3.7.
So your Dockerfile will be:
FROM golang:1.9.6-alpine3.7
WORKDIR /go/src/app
COPY . .
RUN apk add --no-cache git
RUN go-wrapper download # "go get -d -v ./..."
RUN go-wrapper install # "go install -v ./..."
#final stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /go/bin/app /app
ENTRYPOINT ./app
LABEL Name=cloud-native-go Version=0.0.1
EXPOSE 3000

FROM golang:alpine
# important!
ENV GO111MODULE=on
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
ENV GOFLAGS=-mod=vendor
ENV APP_USER app
ENV APP_HOME /go/src/microservices
RUN mkdir /nameApp
ADD . /nameApp
WORKDIR /nameApp
//compile your project
RUN go mod vendor
RUN go build
//open the port 8000
EXPOSE 8000
CMD [ "/nameApp/nameApp" ]

Related

docker build not setting up environment variables using ENV

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

How to pass .env file to docker image in a Go project?

My Go project heriarchy is this:
The main function:
func main() {
path, _ := os.Getwd()
err := godotenv.Load(filepath.Join(path, ".env"))
if err != nil {
log.Fatal("Error loading .env file")
}
server.Init()
}
Here is my docker file content:
FROM golang:alpine AS build-env
LABEL MAINTAINER "Amit Pal <amit.pal#fynchmobility.com>"
ENV GOPATH /go
WORKDIR /go/src
COPY . /go/src/gothamcity
RUN cd /go/src/gothamcity && go build .
FROM alpine
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk*
WORKDIR /app
COPY --from=build-env /go/src/gothamcity/gothamcity /app
EXPOSE 8080
ENTRYPOINT [ "./gothamcity" ]
I ran the following command to build and run the docker image:
docker build -t gcr.io/${PROJECT_ID}/gothamcity:v1.0 .
docker run -ti gcr.io/miles-ee458/gothamcity:v1.0
I got the error:
2021/01/28 14:34:46 Error loading .env file
What am I doing wrong here? How can I pass the .env file to docker image and execute it?
Also, isn't COPY . /go/src/gothamcity copy the entire project to docker image?
COPY . /go/src/gothamcity only copies .env to build container. You have to explicitly copy it to your main container like this:
FROM golang:alpine AS build-env
LABEL MAINTAINER "Amit Pal <amit.pal#fynchmobility.com>"
ENV GOPATH /go
WORKDIR /go/src
COPY . /go/src/gothamcity
RUN cd /go/src/gothamcity && go build .
FROM alpine
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk*
WORKDIR /app
COPY --from=build-env /go/src/gothamcity/gothamcity /app
COPY .env /app
EXPOSE 8080
ENTRYPOINT [ "./gothamcity" ]
Reason is that when you are saying "FROM alpine" this becomes a brand new blank container. That's how multi-stage builds are working.

Why am I getting 404 with Go in docker

This is my Dockerfile
FROM golang:alpine AS build
RUN apk --no-cache add gcc g++ make git
WORKDIR /go/src/app
COPY . .
RUN go get ./...
RUN GOOS=linux go build -ldflags="-s -w" -o ./bin/web-app ./main.go
FROM alpine:3.9
RUN apk --no-cache add ca-certificates
WORKDIR /usr/bin
COPY --from=build /go/src/app/bin /go/bin
EXPOSE 80
ENTRYPOINT /go/bin/web-app --port 80
And this is a simple main.go:
package main
import (
"fmt"
"net/http"
)
func main() {
http.Handle("/", http.FileServer(http.Dir("./public")))
log.Fatal(http.ListenAndServe(":80", nil))
}
The public directory is in the same folder with the main.go file. There is an index.html in the public directory.
When I run go run main.go my website is served properly. But with Docker, I get the 404 page. I suspect it has to do with the placement of the files inside the docker container. Any help is appreciated.
I think you need to create the folder in your alpine container:
RUN mkdir -p /go/bin/public
and make sure to have something in that folder.
or you need to copy the folder and files from the first go container.
and edit your dokcerfile :
WORKDIR /go/bin
ENTRYPOINT web-app --port 80
As LinPy has mentioned you should copy the public folder from build to alpine
And you have to set the WORKDIR to /go in order for the relative path to work
eg.
FROM golang:alpine AS build
RUN apk --no-cache add gcc g++ make git
WORKDIR /go/src/app
COPY . .
RUN go get ./...
RUN GOOS=linux go build -ldflags="-s -w" -o ./bin/web-app ./main.go
FROM alpine:3.9
RUN apk --no-cache add ca-certificates
WORKDIR /go
COPY --from=build /go/src/app/bin /go/bin
COPY --from=build /go/src/app/public /go/public
EXPOSE 80
ENTRYPOINT /go/bin/web-app --port 80

Why can't I build and then run my container locally

I have a multi stage Dockerfile
# Base Build
FROM alpine:3.7 AS base
RUN apk add --no-cache nodejs
WORKDIR /root/app
COPY . .
ARG TARGET_ENV
COPY .env.$TARGET_ENV .env
RUN rm .env.*
RUN npm set progress=false && npm config set depth 0
RUN npm install --only=production
RUN cp -R node_modules prod_node_modules
RUN npm install
RUN npm run build
# Prod Build
FROM base AS release
COPY --from=base /root/app/prod_node_modules ./node_modules
COPY --from=base /root/app/package.json .
COPY --from=base /root/app/package-lock.json .
COPY --from=base /root/app/dist .
CMD npm start
EXPOSE 3000
I'd like to build my container and then run it locally.
It builds just fine but when I run it a hash is output, but the container is not running.
docker build --build-arg TARGET_ENV=local -t express-app .
docker run -d -p 3000:3000 -it express-app
Your container could be crashing on start.
Check the output of $ docker run -p 3000:3000 -it express-app for error messages.

use golang in docker container in multi-stage build

I want to use multi-stage build and I want that at the end I will have Golang inside the running container.
When I run the container and do go version I get error “unknown go”
# build stage
FROM golang:1.11.2-alpine3.8 AS builder-env
ENV CGO_ENABLED=0
ENV GOOS=linux
ADD https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 /usr/bin/dep
RUN chmod +x /usr/bin/dep
RUN mkdir -p $GOPATH/src/github/mtp/myproj
WORKDIR $GOPATH/src/github/mtp/myproj
COPY Gopkg.toml Gopkg.lock ./
RUN dep ensure --vendor-only
COPY . ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o /myproj .
FROM alpine:latest
RUN mkdir /data
COPY --from=builder-env myproj ./
I can do something like this to make it work, but is it a good options ?
FROM alpine:latest
RUN mkdir /data
RUN update-ca-certificates && \
apk add go
COPY --from=builder-env myproj ./
You don't need the go executable to run a compiled program, just the resulting binary. If you add in the missing CMD line to your Dockerfile
CMD ["./myproj"]
I'd expect it would work fine.

Resources