DNS resolution not working with Docker image - docker

I have a Rust program that needs to do some DNS lookups. It works just fine with the following Dockerfile:
FROM rust:1.63.0-bullseye AS build
WORKDIR /app
COPY . .
RUN cargo build --release
EXPOSE 8080
ENTRYPOINT ["/app/target/release/router"]
I've tried to create a somewhat minimalistic image for the program like so:
FROM rust:1.63.0-bullseye AS build
WORKDIR /app
COPY . .
RUN cargo build --release
RUN mkdir -p /app/lib
RUN cp -LR $(ldd ./target/release/router | grep "=>" | cut -d ' ' -f 3) /app/lib
FROM scratch AS websocket-router-rust
WORKDIR /app
COPY --from=build /app/lib /app/lib
COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=build /app/target/release/router /app/router
ENV LD_LIBRARY_PATH=/app/lib
EXPOSE 8080
ENTRYPOINT ["/app/router"]
However, DNS lookups seem to fail when using the latter Dockerfile. Any ideas what files could be missing that should be copied from the build stage?
UPDATE: Got it working by running a file access tracer inside the Docker image while making a request to the server and then copying over all the files that were read with COPY --from... The Dockerfile got a bit messy, but it's less than 30MB now. The main problem was that ldd doesn't return libnss SOs, so those were missing from the image.

You can set the DNS addresses in /etc/docker/daemon.json file:
{
"dns": ["10.0.0.2", "8.8.8.8"]
}

Related

dockerfile COPY does not copy all the files

I do
git clone https://github.com/openzipkin/zipkin.git
cd zipkin
The create a Dockerfile as below
FROM openjdk
RUN mkdir app
WORKDIR /app
COPY ./ .
ENTRYPOINT ["sleep", "1000000"]
then
docker build -t abc .
docker run abc
I then run docker exec -it CONTAINER_ID bash
pwd returns /app which is expected
but I ls and see that the files are not copied
only the directories and the xml file is copied into the /app directory
What is the reason? how to fix it?
Also I tried
FROM openjdk
RUN mkdir app
WORKDIR /app
COPY . /app
ENTRYPOINT ["sleep", "1000000"]
That repository contains a .dockerignore file which excludes everything except a set of things it selects.
That repository's docker directory also contains several build scripts for official images and you may find it easier to start your custom image FROM openzipkin/zipkin rather than trying to reinvent it.

Golang based docker image build works but not scratch based image

I'm able to run a docker image of a web app when using golang:1.13 base, but not when using scratch. The working Dockerfile is:
FROM golang:1.13 AS builder
WORKDIR /app
COPY . .
RUN go build -o server
FROM golang:1.13
COPY --from=builder /app/server /app/server
COPY --from=builder /app/credentials/service-account.json /app/credentials/service-account.json
ENTRYPOINT ["/app/server"]
But when I change the final image base to scratch (line 6) like this:
FROM golang:1.13 AS builder
WORKDIR /app
COPY . .
RUN go build -o server
FROM scratch # <-- CHANGED
COPY --from=builder /app/server /app/server
COPY --from=builder /app/credentials/service-account.json /app/credentials/service-account.json
ENTRYPOINT ["/app/server"]
I get a standard_init_linux.go:211: exec user process caused "no such file or directory" error.
To build the docker image, I use docker build -t myimage ., and to run the image, I use docker run --rm -p 8080:8080 myimage:latest.
The app is a Go based web API that uses Gin framework, and GCP Service Account to access GCP services (the JSON file that I copy on build.)
Provided you are not using CGO (as #jakub mentioned), try disabling CGO in your build.
So change this line in your Dockerfile:
#RUN go build -o server
RUN CGO_ENABLED=0 go build -o server

Golang cannot find package in Docker image

So, I am trying to dockerize a golang application with different directories containing supplementary code for my main file.
I am using gorilla/mux. The directory structure looks like this.
$GOPATH/src/github.com/user/server
|--- Dockerfile
|--- main.go
|--- routes/
handlers.go
|--- public/
index.gohtml
It works on my host machine with no problem. The problem is that when I try to deploy the docker image it does not run and exits shortly after creation. I have tried changing the WORKDIR command in my dockerfile to /go/src and dump all my files there, but still no luck. I have also tried the official documentation on docker hub. Doesn't work either.
My Dockerfile.
FROM golang:latest
WORKDIR /go/src/github.com/user/server
COPY . .
RUN go get -d github.com/gorilla/mux
EXPOSE 8000
CMD ["go","run","main.go"]
My golang main.go
package main
import (
"github.com/gorilla/mux"
"github.com/user/server/routes"
"log"
"net/http"
"time"
)
func main(){
//...
}
I get this error message when I check the logs of my docker image.
Error Message
main.go:5:2: cannot find package "github.com/user/server/routes" in any of:
/usr/local/go/src/github.com/user/server/routes (from $GOROOT)
/go/src/github.com/user/server/routes (from $GOPATH)
Try the following Docker file:
# GO Repo base repo
FROM golang:1.12.0-alpine3.9 as builder
RUN apk add git
# Add Maintainer Info
LABEL maintainer="<>"
RUN mkdir /app
ADD . /app
WORKDIR /app
COPY go.mod go.sum ./
# Download all the dependencies
RUN go mod download
COPY . .
# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# GO Repo base repo
FROM alpine:latest
RUN apk --no-cache add ca-certificates curl
RUN mkdir /app
WORKDIR /app/
# Copy the Pre-built binary file from the previous stage
COPY --from=builder /app/main .
# Expose port 8000
EXPOSE 8000
# Run Executable
CMD ["./main"]
Here, we are creating an intermediate docker builder container, copying the code into it, build the code inside the builder container and then copy the binary image to the actual docker.
This will help in both having all the dependencies in the final container and also, the size of the final image will be very small

How to run a docker container created with go binary?

I am trying to create a docker container with a Dockerfile and a go file binary.
I have two files in my folder: Dockerfile and main, where the latter is a binary of my simple go file.
Contents of Dockerfile:
FROM golang:1.11-alpine
WORKDIR /app
COPY main /app/
RUN ["chmod", "+x", "/app/main"]
ENTRYPOINT ["./main"]
I tried following steps:
sudo docker build -t naive5cr .
sudo docker run -d -p 8080:8080 naive5cr
The error which i see in thru "docker logs " :
standard_init_linux.go:207: exec user process caused "no such file or directory"
my go file content [i think it is irrelevant to the problem]:
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(port(), nil)
}
func port() string {
port := os.Getenv("PORT")
if len(port) == 0 {
port = "8080"
}
return ":" + port
}
the binary "main" runs as expected when run standalone. so there is no problem with the content of go file.
You need to compile with CGO_ENABLED=0 to prevent links to libc on Linux when networking is used in Go. Alpine ships with musl rather than libc, and attempts to find libc result in the no such file or directory error. You can verify this by running ldd main to see the dynamic links.
You can also build on an Alpine based host to link to musl instead of libc. The advantage of a completely statically compiled binary is the ability to run on scratch, without any libraries at all.
go compiles down to native code, so make sure to build your go code on the Docker image, instead of copying the binary to the docker image.
e.g.
FROM golang:1.11-alpine
WORKDIR /app
ADD . /app
RUN cd /app && go build -o goapp
ENTRYPOINT ./goapp
Also as a bonus, here is how to create really tiny Docker images with multistage Docker builds:
FROM golang:1.11-alpine AS build-env
ADD . /src
RUN cd /src && go build -o goapp
FROM alpine
WORKDIR /app
COPY --from=build-env /src/goapp /app/
ENTRYPOINT ./goapp

Mount docker volume to host machine path

I need to access test result files in the host from the container. I know that I need to create a volume which maps between host and container, like below, but I get nothing written to the host.
docker run --rm -it -v <host_directory_path>:<container_path> imagename
Dockerfile:
FROM microsoft/dotnet:2.1-sdk AS builder
WORKDIR /app
COPY ./src/MyApplication.Program/MyApplication.Program.csproj ./src/MyApplication.Program/MyApplication.Program.csproj
COPY nuget.config ./
WORKDIR ./src/MyApplication.Program/
RUN dotnet restore
WORKDIR /app
COPY ./src ./src
WORKDIR ./src/MyApplication.Program/
RUN dotnet build MyApplication.Program.csproj -c Release
FROM builder as tester
WORKDIR /app
COPY ./test/MyApplication.UnitTests/MyApplication.UnitTests.csproj ./test/MyApplication.UnitTests/MyApplication.UnitTests.csproj
WORKDIR ./test/MyApplication.UnitTests/
RUN dotnet restore
WORKDIR /app
COPY ./test ./test
WORKDIR ./test/MyApplication.UnitTests/
RUN dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura
ENTRYPOINT ["dotnet", "reportgenerator", "-reports:coverage.cobertura.xml", "-targetdir:codecoveragereports", "-reportTypes:htmlInline"]
The command at the entry point is working correctly. It is writing the output to the MyApplication.UnitTests/codecoveragereports directory, but not to the host directory.
My docker run looks as follows:
docker run --rm -it -v /codecoveragereports:/app/test/MyApplication.UnitTests/codecoveragereports routethink.tests:latest
What could I be doing wrong?
Looks like a permission issue.
-v /codecoveragereports:/app/***/codecoveragereports is mounting a directory under the root / which is dangerous and you may not have the permission.
It's better to mount locally, like -v $PWD/codecoveragereports:/app/***/codecoveragereports, where $PWD is an environment variable equal to the current working directory.

Resources