2

I'm trying to use GoLand/Cloud Code to build a Golang microservice. But I can't seem to get the Dockerfile nailed down.

FROM --platform=linux/arm64 golang:1.20-alpine  AS build_base
RUN apk add --no-cache git

# Set the Current Working Directory inside the container
WORKDIR /tmp/wave-service

# We want to populate the module cache based on the go.{mod,sum} files.
COPY go.mod .
COPY go.sum .

RUN go mod download

COPY . .

# Unit tests
# CGO_ENABLED=0 go test -v

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o ./out/wave-service ./wave_microservice.go

# Start fresh from a smaller image
FROM --platform=linux/arm64 golang:1.20-alpine
RUN apk add ca-certificates

COPY --from=build_base /tmp/wave-service/out/wave-service /app/wave-service
RUN chmod a+x /app/wave-service

# This container exposes port 8080 to the outside world
EXPOSE 8080

# Run the binary program produced by `go install`
CMD ["/app/wave-service"] 

Returns the error

Waiting for deployments to stabilize...
 - deployment/wave-service: container wave-service-container is backing off waiting to restart
    - pod/wave-service-565995d854-hwhsm: container wave-service-container is backing off waiting to restart
      > [wave-service-565995d854-hwhsm wave-service-container] exec /app/wave-service: exec format error 

I've tried playing around with architectures and OS variables, but I can't seem to find what's going on here.

EDIT:

skaffold.yml

apiVersion: skaffold/v4beta5
kind: Config
build:
  artifacts:
    - image: wave-service
      context: wave-service
      platforms: ["linux/amd64"]
      docker:
        dockerfile: Dockerfile

manifests:
  rawYaml:
    - k8s-pod.yaml 

k8s-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: wave-service
spec:
  containers:
    - name: wave-service
      image: wave-service 
Cate Daniel
  • 724
  • 2
  • 14
  • 30
  • Are you deploying this to Kubernetes? Is the cluster running x86 or ARM hardware? That seems like error you get if you have an x86 cluster, but your Dockerfile is pretty explicit about building an ARM image. (Also consider building the final image `FROM alpine`; you do not need the Go toolchain to run the compiled binary, and this will make the final image much smaller.) – David Maze Jun 10 '23 at 19:40
  • My M1 Mac is an arm machine. I know I can make it smaller, but I need something to work before I start optimizing. – Cate Daniel Jun 10 '23 at 23:22
  • Try to use non-alpine Go image to see if it works. – s0xzwasd Jun 12 '23 at 07:26
  • Echoing the comments above. Additionally, Skaffold (the tool Cloud Code uses under the hood) has built in support for cross platform builds: https://skaffold.dev/docs/builders/cross-platform . If you are deploying to GKE, for example, Skaffold should detect the architecture of your target cluster automatically. – eshaul Jun 12 '23 at 14:04
  • So I tried both `ubuntu:latest` and `golang:latest` and still getting the same error – Cate Daniel Jun 12 '23 at 14:45
  • Do you have any platform indicators in your skaffold.yaml? you could try adding `platforms: ["linux/amd64"]` to force it to build an x86 image (see skaffold.dev/docs/builders/cross-platform for more details). – eshaul Jun 12 '23 at 15:07
  • So I don't have a skaffold.yaml, I'm trying to find a simple example to base off of, but I'm unfamiliar with it – Cate Daniel Jun 12 '23 at 18:29
  • I've added a `skaffold.yaml` and `k8s-pod.yaml` to the problem, but I'm still getting the same error – Cate Daniel Jun 12 '23 at 18:43

2 Answers2

2

So the problem wasn't docker, it was my main go file. It wasn't using the package main so go never found the proper entry point to compile, Changing that worked!

Cate Daniel
  • 724
  • 2
  • 14
  • 30
1

The issue is related to the fact M1 Mac doesn't allow to deploy images built for amd64 because they are not compatible with arm64.

What you need to do is to force the trustBuilder to deploy with buildpacks. Setting trustBuilder=true instructs the pack library to trust the lifecycle binary that is inside the builder image, by mounting the registry credentials into the image and allowing it to perform the image export. In this way, all buildpacks can see the credentials.

In your skaffold.yml file add the trustBuilder option:

build:
  artifacts:
    - image: wave-service
      buildpacks:
        builder: gcr.io/buildpacks/builder:v1
        trustBuilder: true

For completeness, I point out the github issue related to the fix added in the latest versions of skaffold to check the commit code that solved the issue.

Alez
  • 1,913
  • 3
  • 18
  • 22
  • So the problem was actually a go error. I had the main function labeled in the wrong package. Changing that solved my problem. – Cate Daniel Jun 13 '23 at 16:38