Running rust executable built in `rust:latest` does not execute in `debian` - docker

I am using a multistaged build to build and subsequently run the built executable:
FROM rust:latest AS BUILDER
EXPOSE 8081
WORKDIR snitch-backend
RUN apt update -y && apt install vim libclang-dev -y
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim AS RUNNER
WORKDIR snitch-backend
COPY --from=BUILDER /actix-deploy-example/target/release/actix-deploy-example ./
CMD ./actix-deploy-example
When I run the built image I get the following error which indicates a problem of the compiled binary (actually the container just quits. This is for reproduction taken from bashing into the container and executing the binary manually)
./actix-deploy-example: 1: ELF��^#���#8: not found
./actix-deploy-example: 2: Syntax error: ")" unexpected
I'm using an apple silicon M1. It works, though, if I am just running the executable in the same container as the build container (rust:latest).
I am a little confused because I expected the compiled binary to work in any other docker container as long as it is using the same CPU architecture beneath. But apparently I am wrong. I would appreciate someone shedding light on why this multistage build does not work as expected or what the alternative would be.

Related

Docker - dotnet build can't find file

I am trying to make my application work in a Linux container. It will eventually be deployed to Azure Container Instances. I have absolutely no experience with containers what so ever and I am getting lost in the documentation and examples.
I believe the first thing I need to do is create a Docker image for my project. I have installed Docker Desktop.
My project has this structure:
MyProject
MyProject.Core
MyProject.Api
MyProject.sln
Dockerfile
The contents of my Dockerfile is as follows.
#Use Ubuntu Linux as base
FROM ubuntu:22.10
#Install dotnet6
RUN apt-get update && apt-get install -y dotnet6
#Install LibreOffice
RUN apt-get -y install default-jre-headless libreoffice
#Copy the source code
WORKDIR /MyProject
COPY . ./
#Compile the application
RUN dotnet publish -c Release -o /compiled
#ENV PORT 80
#Expose port 80
EXPOSE 80
ENTRYPOINT ["dotnet", "/compiled/MyProject.Api.dll"]
#ToDo: Split build and deployment
Now when I try to build the image using command prompt I am using the following command
docker build - < Dockerfile
This all processed okay up until the dotnet publish command where it errors saying
Specify a project or solution file
Now I have verified that this command works fine when run outside of the docker file. I suspect something is wrong with the copy? Again I have tried variations of paths for the WORKDIR, but I just can't figure out what is wrong.
Any advice is greatly appreciated.
Thank you SiHa in the comments for providing a solution.
I made the following change to my docker file.
WORKDIR app
Then I use the following command to build.
docker build -t ImageName -f FileName .
The image now creates successfully. I am able to run this in a container.

Alpine docker image __isnan: symbol not found

Here's the Dockerfile I am using to build a Golang application and a worker
FROM golang:1.15 AS build
RUN mkdir -p /go/api/proj
WORKDIR /go/api/proj
COPY go.* ./
RUN go mod download
COPY . .
RUN go mod tidy
RUN go build -o proj ./api/
RUN go build -o worker ./worker/
FROM alpine:3.14
WORKDIR /
RUN apk add libc6-compat cmake
RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2
COPY . .
COPY --from=build /go/api/proj/proj .
COPY --from=build /go/api/proj/worker .
EXPOSE 80
CMD ["./worker"]
I had to add libc6-compat because kafka setup in worker wasn't compatible with musl library of alpine
Here's the error I received when trying to run worker in docker container
Error relocating ./worker: __strdup: symbol not found
Error relocating ./worker: __isnan: symbol not found
Error relocating ./worker: __strndup: symbol not found
Can someone suggest what's going wrong here and solution for it?
I am using confluent kafka in worker which may be the reason for this error.
Can someone suggest what's going wrong here and solution for it?
What you are doing here:
RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2
is pretending that Musl is GLIBC. It isn't, and that doesn't work.
From Musl FAQ:
Binary compatibility is much more limited, but it will steadily increase with new versions of musl. At present, some glibc-linked shared libraries can be loaded with musl, but all but the simplest glibc-linked applications will fail if musl is dropped-in in place of /lib/ld-linux.so.2.
Instead of building the worker binary against GLIBC and then trying to run it with Musl, you should build it against Musl.

how would I set up a docker file that compiles using rust image but dependent on another image?

I have a rust service that is dependent on gstreamer and I would like to containerize it. There exists a rust image with debian and a gstreamer image with ubuntu on docker hub. I am still new to creating docker files so I'm not sure what the correct way to go about this is.
This is what I got from following along this log rocket article: https://blog.logrocket.com/packaging-a-rust-web-service-using-docker/. I modified it a bit to what my needs were.
FROM rust:1.51.0 as builder
RUN USER=root cargo new --bin ahps
WORKDIR /ahps
RUN touch ./src/lib.rs
RUN mv ./src/main.rs ./src/bin.rs
COPY ./Cargo.toml ./Cargo.toml
RUN cargo build --release
RUN rm -r src/*
ADD . ./
RUN rm ./target/release/deps/ahps*
RUN cargo build --release
FROM restreamio/gstreamer:latest-prod
ARG APP=/usr/src/ahps
COPY --from=builder /ahps/target/release/ahps ${APP}/ahps
WORKDIR ${APP}
CMD ["./ahps"]
This doesn't work because the rust build depends on gstreamer. I was able to get a working file by using apt-get to install gstreamer on top of the rust image, but the size went from ~700MB to 2.6GB due to the gstreamer image being much more optimized. This is the docker file that makes a 2.6gb image:
FROM rust:1.51.0
RUN apt-get update
RUN apt-get -y install libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio
WORKDIR /ahps
COPY . .
RUN cargo build --release
WORKDIR /ahps/target/release
CMD ["./ahps"]
Overall I'm looking for a way to utilize both images where the gstreamer one is a dependency for my rust build. Thanks in advance.

Undefined References - Golang CGO build fails using Docker, but not on host machine

I'm trying to use the lilliput library for Go. It is only made to run on Linux and OS X.
On my Linux (Debian 10.3) host machine as well as my WSL2 setup (Ubuntu 20.04.1), I have no problems running and building my code (excerpt below).
// main.go
package main
import (
"github.com/discordapp/lilliput"
)
func main() {
...
decoder, err := lilliput.NewDecoder(data)
...
}
However, when I try to put it in a Docker container, with the following configuration, it fails to build.
# Dockerfile v1
FROM golang:1.14.4-alpine AS build
RUN apk add build-base
WORKDIR /src
ENV CGO_ENABLED=1
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY . .
RUN go build -o /out/api .
ENTRYPOINT ["/out/api"]
EXPOSE 8080
I already tried adjusting the Dockerfile with different approaches, for example:
FROM alpine:edge AS build
RUN apk update
RUN apk upgrade
RUN apk add --update go=1.15.3-r0 gcc=10.2.0-r5 g++=10.2.0-r5
WORKDIR /app
RUN go env
ENV GOPATH /app
ADD . /app/src
WORKDIR /app/src
RUN go get -d -v
RUN CGO_ENABLED=1 GOOS=linux go build -o /app/bin/server
FROM alpine:edge
WORKDIR /app
RUN cd /app
COPY --from=build /app/bin/server /app/bin/server
CMD ["bin/server"]
Both result in the following build log:
https://pastebin.com/zMEbEac3
For completeness, the go env of the host machine.
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/kingofdog/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/kingofdog/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/lib/go-1.11"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.11/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/kingofdog/{PROJECT FOLDER}/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build589460337=/tmp/go-build -gno-record-gcc-switches"
I already searched online for this error, but all I could find dealt with errors in the way others imported C libraries in their Go project. Yet, in my case I'm quite sure that it is not a mistake regarding the source code but rather a configuration mistake of the docker container, as the code itself works perfectly fine outside Docker and I couldn't find a similar issue on the lilliput repository.
The alpine docker image is a minimalistic Linux version - using musl-libc instead of glibc - and is typically used for building tiny images.
To get the more featureful glibc - and resolve your missing CGO dependencies - use the non-alpine version of the golang Docker image to build your asset:
#FROM golang:1.14.4-alpine AS build
#RUN apk add build-base
FROM golang:1.14.4 AS build
Did you build the dependencies?
You have to run the script to build the dependencies on Linux.
Script: https://github.com/discord/lilliput/blob/master/deps/build-deps-linux.sh
Their documentation mentions:
Building Dependencies
Go does not provide any mechanism for arbitrary building of dependencies, e.g. invoking make or cmake. In order to make lilliput usable as a standard Go package, prebuilt static libraries have been provided for all of lilliput's dependencies on Linux and OSX. In order to automate this process, lilliput ships with build scripts alongside compressed archives of the sources of its dependencies. These build scripts are provided for OSX and Linux.
In case it still fails, then issue might be linked to glibc-musl because alpine images have musl libc instead of glibc (GNU's libc). So, you can try it with maybe Ubuntu/ CentOS/etc. minimal images or find a way to get glibc on alpine.

libnode-dev installation within docker container

I'm trying to run a node.js application.
I can run it without problems directly on my raspbian buster.
Within a docker container running on the same raspberry pi, I have no such luck.
Dockerfile:
FROM balenalib/raspberry-pi2-debian-node:10-stretch-run
RUN sudo apt-get update
RUN sudo apt-get -y install g++ python make git
WORKDIR /usr/src/app
COPY package.json package.json
RUN JOBS=MAX npm install --production
COPY . ./
CMD ["npm", "start"]
But when I run the same node.js code within a docker container, I'm getting a libnode.so.64 error.
pi#raspberrypi:~/rpi-lora-sensorified/data $ docker logs rpi-lora-sensorified_data_1
> resin-websocket#1.0.1 start /usr/src/app
> node index.js
/usr/src/app/node_modules/bindings/bindings.js:121
throw e;
^
Error: libnode.so.64: cannot open shared object file: No such file or directory
I've tried installing libnode-dev (which I've concluded provides this library) within the container, but I'm getting a
E: Unable to locate package libnode-dev
And yes, I've rebuilt the container without cache but still cannot locate that package.
Any (like really even some pointers would help) idea where do I continue to look further?
So the solution that I can't explain at all is:
I was trying to run the code on debian stretch, while testing if it works on debian buster.. When updating the docker image to buster, everthing works as expected.

Resources