Running microservice go (not found) - docker

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

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

Activate conda environment in docker and using image in WDL

I am developing dockerfile where i need to activate conda environment(working fine)
Dockerfile:
FROM continuumio/miniconda3
WORKDIR /app
# Create the environment:
COPY environment.yml .
RUN conda env create -f environment.yml
# Make RUN commands use the new environment:
SHELL ["conda", "run", "-n", "myenv", "/bin/bash", "-c"]
# The code to run when container is started:
COPY test.py .
ENTRYPOINT ["conda", "run", "--no-capture-output", "-n", "myenv"]
environment.yml
name: myenv
channels:
- conda-forge
dependencies:
- python=3.8
- flask
- numpy
test.py
import numpy as np
# Creating a rank 1 Array
arr = np.array([1, 2, 3])
print("Array with Rank 1: \n",arr)
Building and pushing docker image:
docker build -t docker.io/myaccount/condaset:latest .
docker push docker.io/myaccount/condaset:latest
I tested the docker image which seems to be working fine.
docker run docker.io/myaccount/condaset python test.py
Array with Rank 1:
[1 2 3]
but when i use the same docker image in WDL it gives error.
test.wdl
version 1.0
task my_run
{
input
{
String somevar
}
parameter_meta {
}
command {
set -exo pipefail
python /app/test.py
}
output {
File out = ''
}
runtime {
docker: "docker.io/myaccount/condaset:latest"
}
}
workflow my_wokflow
{
input
{
String somevar
}
call my_run
{
input: somevar=somevar
}
}
input.json
{
"my_wokflow.somevar": "hello_world"
}
Error while running WDL:
java -jar ~/bin/cromwell-58.jar run test.wdl -i input.json
[First 3000 bytes]:+ python /app/test.py
Traceback (most recent call last):
File "/app/test.py", line 1, in <module>
import numpy as np
ModuleNotFoundError: No module named 'numpy'
It seems conda environment become deactivated before calling dockerimage in WDL. How can i fix such issue?
When cromwell runs a container, it overrides the ENTRYPOINT script, so your conda environment does not get activated when the WDL is run.
There are a a couple of different ways you can get the behavior you want.
Add your conda environment to the your PATH in the Dockerfile:
ENV PATH="/opt/conda/envs/myenv/bin:$PATH"
In your WDL, supply an absolute path to python:
/opt/conda/envs/myenv/bin/python /app/test.py
Additionally, in your WDL, the my_run output stanza will result in an error. You need to give a non-empty file name for out:
command {
set -exo pipefail
/opt/conda/envs/myenv/bin/python /app/test.py > out.txt
}
output {
File out = 'out.txt'
}

Docker throwing "{binary} not found" error

I have a very simple Go app that I'm trying to Dockerize.
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", date)
http.HandleFunc("/health", healthCheck)
http.ListenAndServe(":8080", nil)
}
func healthCheck(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "I'm alive!")
}
func date(w http.ResponseWriter, r *http.Request) {
now := time.Now()
fmt.Fprintf(w, now.Format("2006-01-02 15:04:05"))
}
My Dockerfile:
FROM golang:1.14.6
RUN mkdir /app
COPY date.go /app
WORKDIR /app
RUN go build date.go
RUN groupadd -g 999 appuser && \
useradd -r -u 999 -g appuser appuser
USER appuser
EXPOSE 8080
CMD ['/app/date']
However, when I use docker run to run the app, I get the following error:
/bin/sh: 1: [/app/date]: not found
I've commented out the CMD ['/app/date'] line and rebuilt the image, and then was able to exec into it by running
docker run -dit goapp
docker exec -ti [containerid] /bin/bash
This takes me into the /app folder where I do see the date file. And I am able to run /app/date without any issues. I'm not sure what I'm doing wrong.
The CMD is interpreted as JSON, so you need to change the single quotes to double quotes.
CMD ["/app/date"]
This is specified in the Dockerfile documentation:
The exec form is parsed as a JSON array, which means that you must use double-quotes (") around words not single-quotes (').

Connect to docker container that runs golang server using netcat

I'm new to docker. Trying to create an image from a simple server written in golang. Server listens on port 8000 and writes current time to the client once per second.
package main
import (
"fmt"
"io"
"net"
"time"
)
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
panic(err)
}
for {
conn, err := listener.Accept()
fmt.Println("Received connection")
if err != nil {
fmt.Println(err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
for {
_, err := io.WriteString(conn, time.Now().Format("15:04:05\n"))
if err != nil {
return
}
time.Sleep(1 * time.Second)
}
}
My Dockerfile
FROM golang
WORKDIR $GOPATH/src/
RUN mkdir -p sandbox/clock1
WORKDIR $GOPATH/src/sandbox/clock1
COPY . .
RUN go get -d -v ./...
RUN go install -v ./...
EXPOSE 8000
ENTRYPOINT /go/bin/clock1
I start docker container with command
docker run -p 8000:8000 -it --name clock1 clock1
And then I'm trying to connect to server using docker IP address
nc 192.168.1.3 8000
netcat fails to connect and exists immediately. Could you please point me to what I'm doing wrong.

Go binary not found when using Dockerfile

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...

Resources