Can I pass Docker run arguments to optional Golang flags? [duplicate] - docker

This question already has answers here:
Pass optional arguments when running a Docker image
(1 answer)
How to pass arguments to Shell Script through docker run
(8 answers)
Can you pass flags to the command that docker runs?
(2 answers)
Closed 3 years ago.
I want to run a simple go script in a docker container. The script has some flags like the two examples bellow.
Flags:
dataSource := flag.String("input", "", "Path")
...
concurrency := flag.Int("concurrency", 10, "Concurrency")
flag.Parse()
Some flags have defaults set and are optional. Others are mandatory to be set by the user. How would I pass arguments in the docker run command to the go script without having the user to enter all arguments?
Dockerfile:
FROM golang:alpine AS builder
RUN apk update && apk add --no-cache git
WORKDIR $GOPATH/go/src/app
ENV GOBIN=/usr/local/bin
COPY . .
RUN go get github.com/lib/pq
RUN go build -o /go/bin/Import
FROM scratch
COPY --from=builder /go/bin/Import /go/bin/Import
ENTRYPOINT ["/go/bin/Import""]
I've read the docs about ENTRYPOINT but could not find anything suitable for me. Is it even possible or doesn't it make sense?
I've read through posts like this one: Pass optional arguments when running a Docker image . They simply pass single arguments, how would I define the default value for those?
Thanks for any help

Related

Pass --build-arg to Dockerfile FROM instruction [duplicate]

This question already has answers here:
Using ARG in FROM in dockerfile
(2 answers)
Closed 2 months ago.
How do I pass --build-arg to a Dockerfile in order to populate the version of the image?
e.g.
FROM <custom_Image>:$VERSION
Note: the docker build statement is inside a bash script.
You use the ARG statement in your Dockerfile like this
ARG myversion
FROM nginx:${myversion}
Then you can pass it from your build command like this
docker build --build-arg myversion=xyzzy .
It'll then complain that an 'xyzzy' version of nginx doesn't exist, proving that it's trying to get nginx:xyzzy.
It shouldn't matter that the docker build statement is in a bash script.

Why both CMD and entrypoint defined in some images? [duplicate]

This question already has answers here:
What is the difference between CMD and ENTRYPOINT in a Dockerfile?
(19 answers)
Closed 1 year ago.
I have seen some images that based on the inspect have both CMD and ENTRYPOINT set.
What is the idea of this? What use cases are served when both are set?
per https://docs.docker.com/engine/reference/builder/#cmd
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
this means that CMD can be used as a list of parametres to the entrypoint.
UPD 1
the idea here is that you can specify the entrypoint (binary to run at start) and then have CMD parameters to this entrypoint which can be overridden.
UPD 2
Here is an example:
cat Dockerfile
FROM busybox
ENTRYPOINT ["ls"]
CMD ["etc"]
now that if you build the image and run it without any arguments, it will product the list with the content of etc folder
$ docker run lister
group
hostname
hosts
localtime
mtab
network
passwd
resolv.conf
shadow
if you do specify the arguments though, you can override the CMD and list the content of a different folder
$ docker run lister var
spool
www
so the executable stays the same in both cases, while the CMD in the Dockerfile is defining the default argument to this binary. Then we can override when we run the container.

How does a docker container from SCRATCH execute a binary?

The docker documentation says that you can build this minimal image:
FROM scratch
ADD hello /
CMD ["/hello"]
Presumably the way this works is that the CMD step is using the default shell (that is, bin/sh, per https://stackoverflow.com/a/21564990/10900852) to run the hello executable.
But if SCRATCH is really entirely empty, where is bin/sh coming from? Why does my image contain a shell?
A container built from scratch does NOT have anything inside at the beginning, so your image contains no /bin/sh.
However, there are two formats of CMD which matters here:
CMD ["/hello"]
CMD /hello
The first format specifies a full command and is called directly via execve(2). The actual process executed is as exactly as ["/hello"] (i.e. argc == 1)
The second format specifies a "entrypoint parameter" and is passed as a single argument to entrypoint, so Docker will attempt to run ["/bin/sh", "-c", "/hello"] with argc == 3 and fail.
You can replace the CMD line with CMD /hello and observe it for yourself.

Bust cache bust within Dockerfile without providing external build args

We have a Dockerfile, where at a certain point would like no caching to happen.
Currently we are using
ENV CACHE_BUST=$($RANDOM)
Upon further inspection, funny enough that gets cached:
Step 1/1 : ENV CACHE_BUST=$($RANDOM)
---> Using cache
Is there any way from inside the Dockerfile to bust the cache without passing in a unique build-arg (Like docker build . --build-arg CACHE_BUST=$(date +%s)) in the build step?
Update: Reviewing this one, it looks like you injected the cache busting option incorrectly in two ways:
ENV is not an ARG
The $(x) syntax is not a variable expansion, you need curly brackets (${}), not parenthesis ($()).
To break the cache on the next run line, the syntax is:
ARG CACHE_BUST
RUN echo "command with external dependencies"
And then build with:
docker build --build-arg CACHE_BUST=$(date +%s) .
Why does that work? Because during the build, the values for ARG are injected into RUN commands as environment variables. Changing an environment variable results in a cache miss on the new build.
To bust the cache, one of the inputs needs to change. If the command being run is the same, the cache will be reused even if the command has external dependencies that have changed, since docker cannot see those external dependencies.
Options to work around this include:
Passing a build arg that changes (e.g. setting it to a date stamp).
Changing a file that gets included into the image with COPY or ADD.
Running your build with the --no-cache option.
Since you do not want to do option 1, there is a way to do option 3 on a specific line, but only if you can split up your Dockerfile into 2 parts. The first Dockerfile has all the lines as you have today up to the point you want to break the cache. Then the second Dockerfile has a FROM line to depend on the first Dockerfile, and you build that with the --no-cache option. E.g.
Dockerfile1:
FROM base
RUN normal steps
Dockerfile2
FROM intermediate
RUN curl external.jar>file.jar
RUN other lines that cannot be cached
CMD your cmd
Then build with:
docker build -f Dockerfile1 -t intermediate .
docker build -f Dockerfile2 -t final --no-cache .
The only other option I can think of is to make a new frontend with BuildKit that allows you to inject an explicit cache break, or unique variable that results in a cache break.
You can add ADD layer with the downloading of some dynamic page from stable source in the beginning of Dockerfile. Image will be always re-built without using a cache.
Just an example of Dockerfile:
FROM alpine:3.9
ADD https://google.com cache_bust
RUN apk add --no-cache wget
p.s. I believe you are aware of docker build --no-cache option.

How to avoid the Docker build cache for a single command/RUN? [duplicate]

This question already has an answer here:
Docker RUN ls shows cached files
(1 answer)
Closed 4 years ago.
I'm using RUN ls /some/directory for "printf-debugging" of a Dockerfile. After the command has been run once and no command has changed before, the result is cached and no output is provided.
I can change the command with a part which is never executed, e.g. append || echo some changing number] which is annoying for every run or turn off the build cache which affects more RUNs than necessary and thus slows down the development of the Dockerfile.
Is there a way to disable the cache for just one RUN without any of the described downsides?
Would using a build arg be an acceptable solution?
# Dockerfile
FROM alpine
RUN echo "executed 1"
# Above this will be cached, below will be retriggered with new builds
ARG BUILD
RUN echo "executed 2"
Then, running with different build arg number to re-run everything below the ARG
$ docker build --build-arg BUILD=2 -t temp .
Or, with using date as the build number:
$ docker build --build-arg BUILD="$(date)" -t temp .

Resources