Pass a bash script command-line option from a Dockerfile - bash

I have a bash script that is run as part of a Dockerfile build process.
my_script.sh
poetry install
Dockerfile
RUN ./my_script.sh
What I would like to do is optionally invoke poetry install -vvv when I build the Docker image.
I tried something like:
Dockerfile
ARG POETRY_OPTION="-vvv"
RUN ./my_script.sh ${POETRY_OPTION}
and my_script.sh
poetry install $1
But that isn't being honored. It runs as if that option is not there.
It seems to me that maybe that works for regular arguments, but won't work for "options".

You can have the ARG inside of the Dockerfile as ARG POETRY_OPTION. While running the docker build command use docker build --build-arg POETRY_OPTION="vvv" .

Related

Docker run fail with ruby

I have a little problem, when i run my container this:
docker run -it emails_request cucumber -t #teste_inserindo_email
It's ok.
But, when i run this:
docker run it emails_request
Where my #teste_inserindo_emails, is on my dockerfile
WORKDIR /app
COPY Gemfile .
RUN bundle install && bundle clean
COPY . /app
EXPOSE 80
RUN cucumber -t #teste_inserindo_email
#CMD ["cucumber", "-t", " #teste_inserindo_email"]
Not found, return:
$ docker run -t emails_request
irb(main):001:0>
Or:
$ docker run emails_request
Switch to inspect mode.
what's your question exactly? you can just run it manually by firing up a container with an interactive terminal from your image, and then run the commands you want, or have a script in the image (or mounted as a volume) and then pass the script as the entry command instead.
docker run -it IMAGE_ID bash (for running manual commands)
if you want to use a script instead, put an ENTRYPOINT script in your Dockerfile instead

docker run script which exports env variables

I've search some of the questions already like docker ENV vs RUN export, which explains differences between those commands, but didn't help in solving my problem.
For example I have a script called myscript:
#!/bin/bash
export PLATFORM_HOME="$(pwd)"
And have following lines in Dockerfile:
...
COPY myscript.sh /
RUN ./myscript.sh
I've also tried to use ENTRYPOINT instead of RUN or declaring variable before calling the script, all that with no success.
What I want to achieve is that PLATFORM_HOME can be referenced from other Dockerfiles which use that one as a base. How to do it ?
There's no way to export a variable from a script to a child image. As a general rule, environment variables travel down, never up to a parent.
ENV will persist in the build environment and to child images and containers.
Dockerfile
FROM busybox
ENV PLATFORM_HOME test
RUN echo $PLATFORM_HOME
Dockerfile.child
FROM me/platform
RUN echo $PLATFORM_HOME
CMD ["sh", "-c", "echo $PLATFORM_HOME"]
Build the parent
docker build -t me/platform .
Then build the child:
→ docker build -f Dockerfile.child -t me/platform-test .
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM me/platform
---> 539b52190af4
Step 2/3 : RUN echo $PLATFORM_HOME
---> Using cache
---> 40e0bfa872ed
Step 3/3 : CMD sh -c echo $PLATFORM_HOME
---> Using cache
---> 0c0e842f99fd
Successfully built 0c0e842f99fd
Successfully tagged me/platform-test:latest
Then run
→ docker run --rm me/platform-test
test
I think export sets the environment variables for the child processes. So it really doesn't matter if you do RUN or ENTRYPOINT. In reading linux source command not working when building Dockerfile, I feel source command cannot help either.
You need to use ENV if you want to set the environment variables in Dockerfile.
Just use ENV PLATFORM_HOME=$(pwd) in your Dockerfile. Variable will be accessible in every container you will create from the Dockerfile.

How do I Run Docker cmds Exactly Like in a Dockerfile

There seems to be a difference between how Docker runs commands in a Dockerfile versus running commands manually after starting a container. This seems to be due to the kind of shells you can start, a (I assume) non-interactive shell with a Dockerfile vs an interactive one when running something like docker run -it <some-img-id>.
How can I debug running commands in a Docker container so that it runs exactly like the commands are run from a Dockerfile? Would just adding /bin/bash --noprofile to the run cmd suffice? Or is there anything else different about the environment when started from a Dockerfile?
What you are experiencing is the behavior because of the shell. Most of us are used to using the bash shell. So generally we would attempt to run the commands in the below fashion
For new container
docker run -it <imageid> bash
For existing container
docker exec -it <containerid> bash
But when we specify some command using RUN directive inside a Dockerfile
RUN echo Testing
Then it is equivalent to running /bin/sh -c 'echo Testing'. So you can expect certain differences as both the shells are different.
In Docker 1.12 or higher you have a Dockerfile directive named SHELL this allows you to override the default SHELL
SHELL ["/bin/bash", "-c"]
RUN echo Testing
This would make the RUN command be executed as bash -c 'echo Testing'. You can learn more about the SHELL directive here
Short answer 1:
If Dockerfile don't use USER and SHELL commands, then this:
docker --entrypoint "/bin/sh -c" -u root <image> cmd
Short answer 2:
If you don't squash or compress image after the build, Docker creates images layers for each of the Dockerfile commands. You can see them in the output of docker build at the end of each step with --->:
Step 2/8 : WORKDIR /usr/src/app
---> 5a5964bed25d # <== THIS IS IMAGE ID OF STEP 2
Removing intermediate container b2bc9558e499
Step 3/8 : RUN something
---> f6e90f0a06e2 # <== THIS IS IMAGE ID OF STEP 3
Removing intermediate container b2bc9558e499
Look for the image id just before the RUN step you want to debug (for example you want to debug step 3 on above, take the step 2 image id). Then just run the command in that image:
docker run -it 5a5964bed25d cmd
Long answer 1:
When you run docker run [image] cmd Docker in fact starts the cmd in this way:
Executes the default entrypoint of the image with the cmd as its argument. Entrypoint is stored in the image on build by ENTRYPOINT command in Dockerfile. Ie if cmd is my-app and entrypoint is /bin/sh -c, it executes /bin/sh -c my-app.
Starts it with default user id of the image, which is defined by the last USER command in Dockerfile
Starts it with the environment variables from all ENV commands from image's Dockerfile commulative
When docker build runs the Dockerfile RUN, it does exatly the same, only with the values present at that time (line) of the Dockerfile.
So to be exact, you have to take the value of ENVs and last USER command before your RUN line, and use those in the docker run command.
Most common images have /bin/sh -c or /bin/bash -c as entrypoint and most likely the build operates with root user. Therefore docker --entrypoint "/bin/bash -c" -u root <image> cmd should be sufficient

Referencing the first argument passed to the docker entrypoint?

I'm trying to obtain the value of the first argument I pass to the Docker Entrypoint. I received an answer earlier on how to do this. Here is the link:
Referencing a dynamic argument in the Docker Entrypoint
So I setup an experiment to see if this works:
Here's my Dockerfile:
FROM alpine:3.3
MAINTAINER ole.ersoy#gmail.com
RUN apk add --update --no-cache --no-progress bash
COPY run.sh .
ENTRYPOINT /run.sh
And the run.sh entrypoint:
#!/bin/sh
echo The first argument is: $1
I then build this:
docker build -t test .
And run the image:
ole#MKI:~/docker-test$ docker run test one
The first argument is:
I was expecting:
ole#MKI:~/docker-test$ docker run test one
The first argument is: one
Thoughts?
TIA,
Ole
Change ENTRYPOINT to next:
ENTRYPOINT ["bash", "run.sh"]
It works for me. Read more about entrypoint args here https://docs.docker.com/engine/reference/builder/#entrypoint

how to pass a --login into docker build

I have some script that I need to run inside the container, and somehow it only run if I run it inside a bash --login.
I normally run my docker: docker build -t sometags . and I noticed it only run bash without --login.
I know I can just use bash -l -c "some-command-here" but I'd say it's my final fallback if nothing can helps.
so, tl;dr: how can I achieve something like this in my Dockerfile
#dockerfile
RUN bash --login
RUN some-script
and then, I'll just run it with: docker build -t x/y:z .
updated:
the scripts I want to run is things like: gem install bundler, and bundle install.

Resources