I have a shell script like create.sh inside a docker container.
I connected to container like below.
docker exec -it --user=root <container_id> /bin/sh
and when i try to run the script inside the container i am getting an error .
sh-4.2# sh create.sh
create.sh: line 1: !/bin/bash: No such file or directory
Any ideas?
You must have put #!/bin/bash at the beginning of your .sh script. So it searches for /bin/bash to run this script, but cannot find it because bash is not installed.
Related
I am trying to create a .bat file that will back-up the database inside the container. After the first command (that is used to enter the container) the next one is ignored.
docker exec -it CONTAINER_NAME /bin/bash
cd /var/opt/mssql/data
Any ideas why? If I'm trying to manually write cd /var/opt/mssql/data in the opened cmd it works.
When running docker exec -it CONTAINER_NAME /bin/bash, you are opening a bash-shell INSIDE the docker container.
The next command, i.e. cd /var/opt/mssql/data, is only executed, if the previous command, docker exec -it CONTAINER_NAME /bin/bash has exited successfully, which means that the shell on the docker container has been closed/exited.
This means that cd /var/opt/mssql/data is then executed on the local machine and not inside the docker container.
To run a command inside the docker container, use the following command
docker exec -it CONTAINER_NAME /bin/bash -c "<command>"
Although it may be better to create a script inside the container during the build process or mount a script inside the docker container while starting the container and then simply call this script with the above mentioned command.
I have pulled one docker image and docker container is running successfully as well. But I want to run one shell script in the running docker. The shell script is located in my hard disk. I am unable to find out which command to use and how to give pathname of the shell file so that it can be executed in running docker.
Please guide me.
Regards
TL;DR
There are two ways that could work in your case.
You can run one-liner-script using docker exec sh/bash with -c argument:
docker exec -i <your_container_id> sh -c 'sh-command-1 && sh-command-2 && sh-command-n'
You can copy shell script into container using docker cp and then run it in docker context:
docker cp ~/your-shell-script.sh <your_container_id>:/tmp
docker exec -i <your_container_id> /tmp/your-shell-script.sh
Precaution
Not all containers allow to run shell scripts in their context. You can check it executing any shell command in docker:
docker exec -i <your_container_id> echo "Shell works"
For future reference check section Understand how CMD and ENTRYPOINT interact
Docker Exec One-liner
docker exec -i <your_container_id> sh -c 'sh-command-1 && sh-command-2 && sh-command-n'
If your container has sh or bash or BusyBox shell wrapper (such as alpine, you can send one-line shell script to container's shell.
Limitations:
only short scripts;
hard to pass command-line arguments;
only if your container has shell.
Docker Copy and Execute Script
docker cp ~/your-shell-script.sh <your_container_id>:/tmp
docker exec -i <your_container_id> /tmp/your-shell-script.sh -arg1 -arg2
You can copy script from host to container and then execute it.
You can pass arguments to the script.
You can run script with root credentials with -u root: docker exec -i -u root <your_container_id> /tmp/your-shell-script.sh -arg1 -arg2
You can run script interactively with -t: docker exec -it <your_container_id> /tmp/your-shell-script.sh -arg1 -arg2
Limitations:
one more command to execute;
only if your container has shell.
I have a docker container with the basic ubuntu image. I use the following command to start it.
docker container run -it -d -v c:\Git\ENGINE_LIB_DIR:/ENGINE_LIB_DIR:ro --name ibuntu ubuntu
inside the mounted volume is a Java JDK and a script which looks like this:
#!/bin/bash
echo "export JAVA_HOME=/ENGINE_LIB_DIR/jdk/" >> ~/.bashrc;
echo "export PATH=${PATH}:/ENGINE_LIB_DIR/jdk/bin/" >> ~/.bashrc;
exec bash
So it basically adds the mounted java to the path to make it useable. This script works, as long as I am executing it from the ubuntu bash inside the container. If I try to use
docker exec -it ibuntu sh -c "sh /ENGINE_LIB_DIR/action.sh"
from outside the container it does not give any error message, whereas
docker exec -it ibuntu sh -c "java -version"
Returns "java: not found". So I suspect the script is not executed properly. I tried absolute paths, just without "sh -c" and basically any other method I found by googeling.
My goal is to easily use a java jdk provided inside a docker container to build a project. I am gladful for any help.
Edit:
I tried the /bin/bash -ic approach from #itachi. It still says java: not found, while the shell call gives back that error:
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
sh: 0: Can't open ./ENGINE_LIB_DIR/action.sh
Edit 2:
I managed to narrow the behaviour down to the docker exec command. I setup the container with docker container run -it -d -v c:\Git\ENGINE_LIB_DIR:/ENGINE_LIB_DIR:ro --entrypoint /ENGINE_LIB_DIR/action.sh --name ibuntu ubuntu /bin/bash. The java path variable is functioning when attached to the container, but when i execute docker exec ibuntu sh -c "java -version" it still says sh: 1: java: not found. I would be grateful for any idea.
Here is my Dockerfile:
FROM ros:kinetic-ros-core-xenial
CMD ["bash"]
If I run docker build -t ros . && docker run -it ros, and then from within the container echo $PATH, I'll get:
/opt/ros/kinetic/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
If I exec into the container (docker exec -it festive_austin bash) and run echo $PATH, I'll get:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Why are the environment variables different? How can I get a new bash process on the container with the same initial environment?
The ENTRYPOINT command is only invoked on docker run, not on docker exec.
I assume that this /ros_entrypoint.sh script is responsible for adding stuff to PATH. If so, then you could do something like this for docker exec:
docker exec -it <CONTAINER_ID> /ros_entrypoint.sh bash
docker exec only gets environment variables defined in Dockerfile with instruction ENV. With docker exec [...] bash you additionally get those defined somewhere for bash.
Add this line to your Dockerfile:
ENV PATH=/opt/ros/kinetic/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
or shorter:
ENV PATH=/opt/ros/kinetic/bin:$PATH
This is old question but since it's where google directed me I thought I'll share solution I ended up using.
In your entrypoint script add a section similar to this:
cat >> ~/.bashrc << EOF
export PATH="$PATH"
export OTHER="$OTHER"
EOF
Once you rebuild your image you can exec into your container (notice bash is invoked in interactive mode):
docker run -d --rm --name container-name your_image
docker exec -it container-name /bin/bash -i
If you echo $PATH now it should be the same as what you have set in .bashrc
I have shell script on my host. I've installed docker container with meteord image. I have it running, however I would like to execute this shell script inside meteord docker image. Is that possible?
Yes. That is possible but you will have to copy the script in the container as follow:
docker cp <script> <container-name/id>:<path>
docker exec <container-name/id> <path>/<script>
For example:
docker cp script.sh silly_nightingale:/root
docker exec silly_nightingale /root/script.sh
Just make sure the script has executable permissions. Also, you can copy the script at build time in Dockerfile and run it using exec afterwards.
Updated:
You can also try docker volume for it as follow:
docker run -d -v /absolute/path/to/script/dir:/path/in/container <IMAGE>
Now run the script as follow:
docker exec -it <Container-name> bash /path/in/container/script.sh
Afterwards you will be able to see the generated files in /absolute/path/to/script/dir on host. Also, make sure to use absolute paths in scripts and commands to avoid redirection issues. I hope it helps.