Go binary not found when using Dockerfile - docker

I am following Go's Docker instructions. Their example works for me. I am now trying to modify it to run a tcp server:
go get github.com/Kelindar/tcp
Add a Dockerfile:
FROM golang
ADD . /go/src/github.com/Kelindar/tcp
RUN go install github.com/Kelindar/tcp
ENTRYPOINT /go/bin/tcp
EXPOSE 8080
I then build it:
docker build --no-cache -t tcp .
build output:
Sending build context to Docker daemon 322kB
Step 1/5 : FROM golang
---> 9fe4cdc1f173
Step 2/5 : ADD . /go/src/github.com/Kelindar/tcp
---> 10abce658324
Step 3/5 : RUN go install github.com/Kelindar/tcp
---> Running in 59dc47b30474
Removing intermediate container 59dc47b30474
---> 8fab53d2882c
Step 4/5 : ENTRYPOINT /go/bin/tcp
---> Running in 18d4b5befccb
Removing intermediate container 18d4b5befccb
---> 073fdb78a481
Step 5/5 : EXPOSE 8080
---> Running in 8ee2b7bc0cba
Removing intermediate container 8ee2b7bc0cba
---> 8bf9f82d4fef
Successfully built 8bf9f82d4fef
Successfully tagged tcp:latest
Now, I run it:
docker run --name test --rm tcp
I get an error:
/bin/sh: 1: /go/bin/tcp: not found
Not really sure where to go on this.

There are two problems here:
The package github.com/Kelindar/tcp does not contain a main function, thus it can't produce a binary to be executed.
There is no main package, and every go program needs a main package with a main function
Whether you run go build or go install in this repository, you will see that nothing will happen, since your package is actually a library.
Now if you add a cmd/tcp_server folder with a tcp_server.go file like this:
package main
import (
"fmt"
"log"
"net"
"github.com/kelindar/tcp"
)
func main() {
closingChan := make(chan bool)
onAccept := func(c net.Conn) {
// Do something here.
}
l, err := net.Listen("tcp", fmt.Sprintf(":%d", 4242))
if err != nil {
log.Fatalf("Unable to net.Listen: %v", err)
}
server := &tcp.Server{
Closing: closingChan,
OnAccept: onAccept,
}
log.Println("Server ready...")
if err := server.Serve(l); err != nil {
log.Fatalf("Server crashed: %v", err)
}
log.Println("Server stopped")
}
And that you update your Dockerfile to use the command that uses your tcp package:
FROM golang
RUN go get github.com/Kelindar/tcp
RUN go build -o $GOPATH/bin/tcp_server $GOPATH/src/github.com/Kelindar/tcp/cmd/tcp_server/tcp_server.go
ENTRYPOINT tcp_server
EXPOSE 8080
Your server will be working properly within docker:
2019/06/16 05:23:29 Server ready...

Related

Deploy Go Lambda within Docker container

I have a Go Lambda function. I want to host that function in a Docker image/container so that I can test it locally. In this effort, I have followed the instructions provided here. From those instructions, I have the following files:
.
Dockerfile
go.mod
go.sum
main.go
Those files contain the following:
Dockerfile (a copy of the Dockerfile in this section)
FROM alpine as build
# install build tools
RUN apk add go git
RUN go env -w GOPROXY=direct
# cache dependencies
ADD go.mod go.sum ./
RUN go mod download
# build
ADD . .
RUN go build -o /main
# copy artifacts to a clean image
FROM alpine
COPY --from=build /main /main
ENTRYPOINT [ "/main" ]
go.mod (an updated version of this go.mod)
module main
go 1.18
require (
github.com/aws/aws-lambda-go v1.32.1
github.com/aws/aws-sdk-go v1.44.60
)
require github.com/jmespath/go-jmespath v0.4.0 // indirect
go.sum (a modified version of this go.sum)
github.com/aws/aws-lambda-go v1.32.1 h1:ls0FU8Mt7ayJszb945zFkUfzxhkQTli8mpJstVcDtCY=
github.com/aws/aws-lambda-go v1.32.1/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM=
github.com/aws/aws-sdk-go v1.44.60 h1:KTTogelVR+4dWiIPl7eyxoxaJkziChON6/Y/hVfTipk=
github.com/aws/aws-sdk-go v1.44.60/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
main.go (a copy of this main.go)
package main
import (
"context"
"encoding/json"
"log"
"os"
"github.com/aws/aws-lambda-go/events"
runtime "github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-lambda-go/lambdacontext"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/lambda"
)
var client = lambda.New(session.New())
func callLambda() (string, error) {
input := &lambda.GetAccountSettingsInput{}
req, resp := client.GetAccountSettingsRequest(input)
err := req.Send()
output, _ := json.Marshal(resp.AccountUsage)
return string(output), err
}
func handleRequest(ctx context.Context, event events.SQSEvent) (string, error) {
// event
eventJson, _ := json.MarshalIndent(event, "", " ")
log.Printf("EVENT: %s", eventJson)
// environment variables
log.Printf("REGION: %s", os.Getenv("AWS_REGION"))
log.Println("ALL ENV VARS:")
for _, element := range os.Environ() {
log.Println(element)
}
// request context
lc, _ := lambdacontext.FromContext(ctx)
log.Printf("REQUEST ID: %s", lc.AwsRequestID)
// global variable
log.Printf("FUNCTION NAME: %s", lambdacontext.FunctionName)
// context method
deadline, _ := ctx.Deadline()
log.Printf("DEADLINE: %s", deadline)
// AWS SDK call
usage, err := callLambda()
if err != nil {
return "ERROR", err
}
return usage, nil
}
func main() {
runtime.Start(handleRequest)
}
I can successfully run:
go mod tidy
go build
I can also successfully build and run my Docker image using:
docker build -t lambda-fn .
docker run -d -v ~/.aws-lambda-rie:/aws-lambda --entrypoint /aws-lambda/aws-lambda-rie -p 9000:8080 lambda-fn:latest /main
I can see a container based on the lambda-fn image listed, with a status of Running, in Docker desktop. However, when I send the following cURL request, nothing happens:
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
I was expecting some logs to be written based on the contents of the handleRequest function. What am I doing wrong?
If you are running in demon mode (-d) you cannot see the logs.
Remove -d and rerun the command
This is due the empty handler registration. You can set the handler name by passing the extra argument
docker run -d -v ~/.aws-lambda-rie:/aws-lambda --entrypoint /aws-lambda/aws-lambda-rie -p 9000:8080 lambda-fn:latest /main handleRequest

Run shell command while setting ENV in dockerfile [duplicate]

This question already has answers here:
Dockerfile - set ENV to result of command
(7 answers)
Closed 2 years ago.
Inside my dockerfile:
ENV MY_ENCODED_VALUE="bXkgbmFtZSBpcyByYWtpYgo="
ENV MY_DECODED_VALUE=$(echo $MY_ENCODED_VALUE | base64 -d)
in the second line, i want to decode the encoded value and put the decoded value into my environment variable.
But i am getting the following error
Error response from daemon: failed to parse dockerfile: Syntax error - can't find = in "$MY_ENCODED_VALUE". Must be of the form: name=value
What does it even mean? What's supposed to be the right syntax here?
As you've mentioned that you need to use the variable during build time only, this should do the job:
Dockerfile:
FROM node:alpine
ENV MY_ENCODED_VALUE "bXkgbmFtZSBpcyByYWtpYgo="
RUN echo $MY_ENCODED_VALUE | base64 -d > /root/temp
RUN MY_DECODED_VALUE=$(cat /root/temp); echo "Output: $MY_DECODED_VALUE"
Output:
$ docker build -t test .
Sending build context to Docker daemon 2.56kB
Step 1/4 : FROM node:alpine
---> bcfeabd22749
Step 2/4 : ENV MY_ENCODED_VALUE "bXkgbmFtZSBpcyByYWtpYgo="
---> Using cache
---> 81084f4be2e4
Step 3/4 : RUN echo $MY_ENCODED_VALUE | base64 -d > /root/temp
---> Using cache
---> b8ad3a100746
Step 4/4 : RUN MY_DECODED_VALUE=$(cat /root/temp); echo "Output: $MY_DECODED_VALUE"
---> Running in c9c41b92dee0
Output: my name is rakib
Removing intermediate container c9c41b92dee0
---> acfcd422a8ed
Successfully built acfcd422a8ed
Successfully tagged testing:latest
Note:
1) The RUN instruction in the last line of my Dockerfile is for the latter part i.e., the echo command. Assigning variable [MY_DECODED_VALUE=$(cat /root/temp)] just before the echo command ensures that the variable gets set in the same layer where you want to consume it.
2) The way i have used variable assignment, it will not behave as you would expect from an ENV instruction i.e., it will not be available for use across layers. If you want to consume the variable in multiple layers, then you will have to use RUN MY_DECODED_VALUE=$(cat /root/temp); <your-command-that-uses-the-variable>, wherever applicable. Not an elegant one but that's how it works with my solution.

Running microservice go (not found)

The error I'm getting for my Go Module project
/bin/sh: microservice: not found
Dockerfile
FROM golang:1.7.4-alpine
MAINTAINER John Doe
ENV SOURCES /go/src/github.com/john/app/
COPY . ${SOURCES}
RUN cd ${SOURCES} && cgo_enabled=0 go install
ENV PORT 8080
EXPOSE 8080
ENTRYPOINT microservice
microservice.go
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(port(), nil)
}
func port() string {
port := os.Getenv("PORT")
fmt.Println(port)
if len(port) == 0 {
port = "8080"
}
return ":" + port
}
func index(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Hello World.")
}
It's a Go module project. I've created an image using following command.
docker build -t app:1.0.3 .
and running it via
docker run -it -p 8080:8080 app:1.0.3
Created executable file is at /go/bin/app
and current working directory is /go.
So, change the last line of your Dockerfile to this
ENTRYPOINT ./bin/app

How to solve the issue of "undefined: math.Round" while installing app of go using docker

I make golang api's code and I have imported some packages in it like math. But while building an image by running the sudo docker build -t users/micro . Then at one step it will give me the error.
Error
Step 6/8 : RUN go install
---> Running in 454784b3ceef
# bkapiv/users/utils
utils/CommonFunctions.go:189:9: undefined: math.Round
Dockerfile
# Start from a Debian image with the latest version of Go installed
# and a workspace (GOPATH) configured at /go.
FROM golang:1.9.6
WORKDIR /go/src/bkapiv/users
# Copy the local package files to the container's workspace.
ADD . /go/src/bkapiv/users
# Build the outyet command inside the container.
# (You may fetch or manage dependencies here,
# either manually or with a tool like "godep".)
RUN cd /go/src
RUN go-wrapper download # "go get -d -v ./..."
RUN go install
# Run the outyet command by default when the container starts.
ENTRYPOINT /go/bin/users
# Document that the service listens on port 8080.
EXPOSE 8080
Imported packages are
package utils
import (
"bytes"
"fmt"
"math"
"math/rand"
"os/exec"
"reflect"
"sort"
"strconv"
"time"
)
187 func Round(x, unit float64) float64 {
188 // for this line it will giving me the error
189 return math.Round(x/unit) * unit
190 }
How I will resolve my error
The function Round() from the math package was only introduced in Go 1.10 (see the release notes). Your Dockerfile uses an older 1.9.6 version, so you will have to upgrade.

Way to force docker to accept and proceed with building the image with a non zero response/code

I have the following dockerfile which is very simple using Centos:latest as the base image.
docker file exits on any command other than 0 as error code/code
yum check-update returns a status code of 100 for successful operation
The docker file is as follows
FROM centos:latest
MAINTAINER xyz (xyz#gmail.com)
ENTRYPOINT ["/bin/sh", "-lc", "ocp-indent"]
RUN yum -y check-update
When I try to build the image , the process is getting run as follows, but it gets killed without building the image successfully
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos:latest
latest: Pulling from library/centos
7dc0dca2b151: Pull complete
Digest:
sha256:b67d21dfe609ddacf404589e04631d90a342921e81c40aeaf3391f6717fa5322
Status: Downloaded newer image for centos:latest
---> 49f7960eb7e4
Step 2/4 : MAINTAINER xyz (xyz#gmail.com)
---> Running in c5284bbfb10e
---> b2334a38cc19
Removing intermediate container c5284bbfb10e
Step 3/4 : ENTRYPOINT /bin/sh -lc ocp-indent
---> Running in 55b9adafca35
---> 02df626e85d6
Removing intermediate container 55b9adafca35
Step 4/4 : RUN yum check-update
---> Running in 3f9d47e74522
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
* base: mirror.its.dal.ca
* extras: centos.les.net
* updates: centos.les.net
binutils.x86_64 2.27-28.base.el7_5.1
updates
gnupg2.x86_64 2.0.22-5.el7_5
updates
python.x86_64 2.7.5-69.el7_5
updates
python-libs.x86_64 2.7.5-69.el7_5
updates
**The command '/bin/sh -c yum check-update' returned a non-zero code: 100**
yum check-update is expected to exit with status 100 if updates are available, as described in its documentation:
check-update
Implemented so you could know if your machine had any updates that needed to be applied
without running it interactively. Returns exit value of 100 if there are packages available for an update. Also returns a list of the packages to be updated in list format.
Returns 0 if no packages are available for update. Returns 1 if an error occurred. Running in verbose mode also shows obsoletes.
Similarly, the docker RUN command is expected to terminate on any nonzero exit status. If you want to force the command to ignore an exit status of 100 (but still treat other failures as erroneous), you can do so as follows:
RUN yum -y check-update || { rc=$?; [ "$rc" -eq 100 ] && exit 0; exit "$rc"; }
That the Docker RUN command treats any nonzero exit status as a failure is standard UNIX convention (the only successful exit status is 0), and is explicitly implemented in dockerfile/containerbackend.go:
if status := <-waitC; status.ExitCode() != 0 {
close(finished)
logCancellationError(cancelErrCh,
fmt.Sprintf("a non-zero code from ContainerWait: %d", status.ExitCode()))
return &statusCodeError{code: status.ExitCode(), err: status.Err()}
}

Resources