I need to use bash in the scripts of a CI/CD pipeline, so I'm trying with this simple image:
FROM alpine:3.4
RUN apk update -q && apk add --no-cache bash -q
SHELL ["/bin/bash", "--login", "-c"]
RUN echo $0
What I get in my terminal is this:
$ docker build .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM alpine:3.4
---> b7c5ffe56db7
Step 2/4 : RUN apk update -q && apk add --no-cache bash -q
---> Using cache
---> 18b729da453c
Step 3/4 : SHELL ["/bin/bash", "--login", "-c"]
---> Using cache
---> 03ca0df4a543
Step 4/4 : RUN echo $0
---> Running in a65419dafc4b
/bin/bash
Removing intermediate container a65419dafc4b
---> 2963f9e0e563
Successfully built 2963f9e0e563
After that, I run that container and get this:
$ docker run -it 2963f9e0e563
/ $ echo $0
/bin/sh
/ $
(it runs as root but I changed "#" with "$" for this post)
Why is it using sh instead of bash?
The SHELL command only modifies the shell that is used to execute the instructions inside the Dockerfile.
If you want to change the shell that's used for the container runtime, you can add CMD ["/bin/bash"] to your Dockerfile in order to change the container default executable to /bin/bash. You could also specify the executable from the command line using docker run -it <image> /bin/bash.
Related
Served many pages and forums and didn't find a solution. I have the simple docker container with executable .sh file. When I build and run it from Windows - all is fine. Now trying to build it from Ubuntu 18.04 with Docker version 19.03.5.
For rebuild use .sh script that I execute as bash install.sh
go build -o main.sh ./main
docker stop stats
docker container rm stats
docker image rm stats
docker build -t stats .
docker run --name stats -p 8080:8080 stats
My Dockerfile is:
FROM alpine:3.10.1
ARG appPath="app"
RUN mkdir /app/
COPY main.sh /app/main.sh
RUN chmod +x /app/main.sh
COPY resources /app/resources
RUN apk add --no-cache bash
WORKDIR /app
EXPOSE 8080
CMD /bin/bash -c 'ls' && /app/main.sh dev
The output 'install' call is the following:
bash install.sh
stats
stats
Untagged: stats:latest
Sending build context to Docker daemon 38.98MB
Step 1/10 : FROM alpine:3.10.1
---> b7b28af77ffe
Step 2/10 : ARG appPath="app"
---> Using cache
---> 08baa7336701
Step 3/10 : RUN mkdir /app/
---> Using cache
---> fb9870e78322
Step 4/10 : COPY main.sh /app/main.sh
---> Using cache
---> 79bf713855e3
Step 5/10 : RUN chmod +x /app/main.sh
---> Using cache
---> 88bf70f9c6ec
Step 6/10 : COPY resources /app/resources
---> Using cache
---> 2ebf95627a9e
Step 7/10 : RUN apk add --no-cache bash
---> Using cache
---> 39cd823e7f2f
Step 8/10 : WORKDIR /app
---> Using cache
---> 37e6fcea2d65
Step 9/10 : EXPOSE 8080
---> Using cache
---> 4250094c65f6
Step 10/10 : CMD /bin/bash -c 'ls' && /app/main.sh dev
---> Using cache
---> ed41a1efb15b
Successfully built ed41a1efb15b
Successfully tagged stats:latest
main.sh
resources
/bin/sh: /app/main.sh: not found
I don't understand what is wrong. main.sh is there. If I try to execute CMD /bin/bash -c 'ls' && bash main.sh dev then receive main.sh: main.sh: cannot execute binary file.
What is wrong there and how can I fix it?
UPD:
Renamed file that this was binary and shouldn't have .sh in the end.
And tryed again wi the following:
install.sh
#!/bin/bash
go build -o myapp ./main
docker stop stats
docker container rm stats
docker image rm stats
docker build -t stats .
docker run --name stats -p 8080:8080 stats
Dockerfile
FROM alpine:3.10.1
RUN mkdir /app/
COPY myapp /app/myapp
RUN chmod +x /app/myapp
COPY resources /app/resources
RUN apk add --no-cache bash
WORKDIR /app
EXPOSE 8080
CMD /bin/bash -c 'ls' && ./myapp dev
Output was the following:
....
Step 9/9 : CMD /bin/bash -c 'ls' && ./myapp dev
---> Running in 52fc24d26747
Removing intermediate container 52fc24d26747
---> 8d4f415e6dcd
Successfully built 8d4f415e6dcd
Successfully tagged stats:latest
myapp
resources
/bin/sh: ./myapp: not found
Tryed /app/myapp, ./myapp and it doesn't work.
I'm guessing the error message is misleading, and that the real problem is that some library or other Go runtime component is missing from inside your Docker image. Try building your app statically (which means all the things it needs will be bundled into the binary).
CGO_ENABLED=0 go build -o myapp ./main
(And yeah, don't call it main.sh if it's not a shell script. Unix doesn't care, but you are confusing the hell out of your human readers. And actually, don't call it that even if it is. You don't need to know whether grep is a binary, a shell script, or a Python program; the same convention makes sense for your own tools.)
I have to run maven and angular build inside a docker container with sh command as beolw:
docker run -v maven command and then ng build.
How to run/concatenate both commands in single docker run command?
The solution to this is :
sh """
docker run -v ....\\
"maven command" \\
&& cd directory && ng build'
"""
That worked for me.
In order to run multiple commands in docker, use /bin/bash -c with a semicolon ;
In this case, the second command ng build will be executed only if the first command (cd) returns no error or exit status. To avoid this use && instead of ; (semi-colon)
docker run image /bin/bash -c "cd directory && ng build"
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
Input:
- There is Windows machine with Docker Toolbox installed.
- There is a shell script file baz.sh which calls py2dsc-deb.
Problem: py2dsc-deb is not available on Windows.
As I understand correctly, I can pull some Linux distro image from Docker repository, create a container and then execute shell-script file and it will run py2dsc-deb and do its job.
I have pulled:
debian - stretch-slim - 3ad21 - 3 weeks ago - 55.3MB
Now
How do I run my script using debian, something like: docker exec mycontainer /path/to/test.sh?
Running docker --rm debian:stretch-slim does nothing. Doesn't it suppose to run Debian distro at docker-machine ip?
I have tried to keep the container up using docker run -it debian:stretch-slim /bin/bash, then run the script using docker exec 1ef5b ./build.sh, but getting
$ docker exec 745 ./build.sh
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"./build.sh\": stat ./build.sh: no such file or directory"
Does it mean I can't run external script and has to always pass it inside the Docker?
You can execute bash command inside your container by typing
docker exec -ti -u `username` `container_name` bash -c "cd /path/to/ && ./test.sh"
lets say your container name is test_buildbox, you are root and your script stays inside /bin/test.sh You can call this script by typing
docker exec -ti -u root test_buildbox bash -c "cd /bin/ && ./test.sh
Please check if you have correct line endings in your .sh scripts (<LF>) when you built Docker image on Windows.
New to dockers, so please bear with me.
My Dockerfile contains an ENTRYPOINT:
ENV MONGOD_START "mongod --fork --logpath /var/log/mongodb.log --logappend --smallfiles"
ENTRYPOINT ["/bin/sh", "-c", "$MONGOD_START"]
I have a shell script add an entry to database through python script, and starts the server.
The script startApp.sh
chmod +x /addAddress.py
python /addAddress.py $1
cd /myapp/webapp
grunt serve --force
Now, all the below RUN commands are unsuccessful in executing this script.
sudo docker run -it --privileged myApp -C /bin/bash && /myApp/webapp/startApp.sh loc
sudo docker run -it --privileged myApp /myApp/webapp/startApp.sh loc
The docker log of container is
"about to fork child process, waiting until server is ready for connections. forked process: 7 child process started successfully, parent exiting "
Also, the startApp.sh executes fine when I open a bash prompt in docker and run it.
I am unable to figure out what wrong I am doing, help please.
I would suggest you to create an entrypoint.sh file:
#!/bin/sh
# Initialize start DB command
# Pick from env variable MONGOD_START if it exists
# else use the default value provided in quotes
START_DB=${MONGOD_START:-"mongod --fork --logpath /var/log/mongodb.log --logappend --smallfiles"}
# This will start your DB in background
${START_DB} &
# Go to startApp directory and execute commands
`chmod +x /addAddress.py;python /addAddress.py $1; \
cd /myapp/webapp ;grunt serve --force`
Then modify your Dockerfile by removing the last line and replacing it with following 3 lines:
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
Then rebuild your container image using
docker build -t NAME:TAG .
Now you run following command to verify if ENTRYPOINT is /entrypoint.sh
docker inspect NAME:TAG | less
I guess (and I might be wrong, since I'm neither a MongoDB nor a Docker expert) that your combination of mongod --fork and /bin/sh -c is the culprit.
What you're essentially executing is this:
/bin/sh -c mongod --fork ...
which
executes a shell
this shell executes a single command and waits for it to finish
this command launches MongoDB in daemon mode
MongoDB forks and immediately exits
The easiest fix is probably to just use
CMD ["mongod"]
like the official MongoDB Docker does.