chemidy/smallest-secured-golang-docker-image

standard_init_linux.go:207: exec user process caused "exec format error"

andig opened this issue · 8 comments

andig commented

I'm apparently unable to produce a binary that will work in scratch. The Dockerfile below always ends in

standard_init_linux.go:207: exec user process caused "exec format error"

I've only changed build to use make and added GOMODULE. Any idea whats going wrong?

############################
# STEP 1 build executable binary
############################
# golang alpine 1.11.5
FROM golang:alpine as builder

# Install git + SSL ca certificates.
# Git is required for fetching the dependencies.
# Ca-certificates is required to call HTTPS endpoints.
RUN apk update && apk add --no-cache git ca-certificates tzdata alpine-sdk bash && update-ca-certificates

# Create appuser
RUN adduser -D -g '' appuser

WORKDIR $GOPATH/src/gonium/gosdm630/
COPY . .

# Fetch dependencies.

# Using go get.
# RUN go get -d -v

# Using go mod.
RUN GO111MODULE=on go mod download
RUN ["/bin/bash", "-c", "make assets"]

# Build the binary
RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/sdm .

#############################
## STEP 2 build a small image
#############################
FROM scratch

# Import from builder.
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /etc/passwd /etc/passwd

# Copy our static executable
COPY --from=builder /go/bin/sdm /go/bin/sdm

# Use an unprivileged user.
USER appuser

# Run the binary.
ENTRYPOINT ["/go/bin/sdm"]

I just try to use go mo and works like a charm 👍

message : "exec format error" is strange ... are you sure to build for a linux and amd64 arch ?

you can try to build out of docker and try to run the binary

GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/sdm .
/go/bin/sdm
andig commented

I'm running this on Mac (means GOOS=linux might be a problem). I've replaced linux with darwin:

Step 8/18 : RUN GO111MODULE=on CGO_ENABLED=0 GOOS=darwin go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/sdm .
---> Running in de702725ab92
Removing intermediate container de702725ab92
---> 4009d32b03af
Step 9/18 : RUN chmod +x /go/bin/sdm
---> Running in 7b3dd01fdc8d
Removing intermediate container 7b3dd01fdc8d
---> 36963ab4efc4
Step 10/18 : RUN ls -l /go/bin/sdm
---> Running in 7659debbd548
-rwxr-xr-x    1 root     root        767280 Feb 25 12:52 /go/bin/sdm
Removing intermediate container 7659debbd548
---> 6d1a8d0d69d5
Step 11/18 : RUN /go/bin/sdm
---> Running in c9308bec1763
/go/bin/sdm: line 2: syntax error: unexpected newline
The command '/bin/sh -c /go/bin/sdm' returned a non-zero code: 2

It doesn't even run in the build container. Same result when removing GOOS entirely. Its still:

/go/bin/sdm: line 2: syntax error: unexpected newline

Mhhm. Wrong base image for running on Darwin?

Please try the projet without changes.

  • if it works, change just the binary name
  • if it works change the go mod,
  • ....

The original command is :

RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/hello .
andig commented

I need to make three changes in order to run the build:

As I'm using modules I need to force them since

Step 6/16 : RUN go mod download
---> Running in f4212b13d817
go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'

so I use:

RUN GO111MODULE=on go mod download

Then this also doesn't work for the actual build as it will be missing packages:

Step 8/16 : RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/sdm ./...
---> Running in 093e36fceea1
homie.go:11:2: cannot find package "github.com/eclipse/paho.mqtt.golang" in any of:
    /usr/local/go/src/github.com/eclipse/paho.mqtt.golang (from $GOROOT)
    /go/src/github.com/eclipse/paho.mqtt.golang (from $GOPATH)

instead:

RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/sdm .

Plus I had to add a make step for generated files:

RUN ["/bin/bash", "-c", "make assets"]

And still:

Step 8/16 : RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o /go/bin/sdm .
---> Running in 3349f4d9bb61
Removing intermediate container 3349f4d9bb61
---> 04d378b6ee97
Step 9/16 : RUN /go/bin/sdm
---> Running in a68b023f86cb
/bin/sh: /go/bin/sdm: Permission denied
The command '/bin/sh -c /go/bin/sdm' returned a non-zero code: 126

The build is run on OSX. No idea what else to try.

OK :)

The purpose of this repository/article is to run a go app in a container as non root !!!

https://medium.com/@chemidy/create-the-smallest-and-secured-golang-docker-image-based-on-scratch-4752223b7324#6631

so try to remove the following line

# Use an unprivileged user.
USER appuser

If it works, you need to find which package/function needs another rigths ?

But i think this is another thing, like writing files, or reading something ....

As i can see an error message from your app :

/bin/sh: /go/bin/sdm: Permission denied
The command '/bin/sh -c /go/bin/sdm' returned a non-zero code: 126

You have to check what is error 126 with a not very helpful 'Permission denied' label

andig commented

Still same thing without the user:

/bin/sh: /go/bin/sdm: Permission denied
The command '/bin/sh -c /go/bin/sdm' returned a non-zero code: 126

I've meanwhile run the image naked and its working:

❯ docker run -it golang@sha256:8dea7186cf96e6072c23bcbac842d140fe0186758bcc215acb1745f584984857
/go # vi
/go # CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o bin/test .
/go # bin/test
ok

I appreciate your help but it feels I'm trying to force it beyond the scope of this repo :/ If you're still interested you could take a look yourself if you really wish: https://github.com/gonium/gosdm630

ok i will check later 👍

andig commented

Darn, found it. The trick is to build main:

cmd/sdm/main.go

When building . it will generate some sort of go package format, i.e. the "binary" has totally different content then...