Update PATH in Centos Docker image (alternative to Dockerfile ENV) - docker

I'm provisioning docker Centos image with Packer and using bash scripts instead of Dockerfile to configure image (this seems to be the Packer way). What I can't seem to figure out is how to update PATH variable so that my custom binaries can be executed like this:
docker run -i -t <container> my_binary
I have tried putting .sh file in /etc/profile.d/ folder and also writing directly to /etc/environment but none of that seems to take effect.
I'm suspecting it has something to do with what shell Docker uses when executing commands in a disposable container. I thought it was Bourne Shell but as mentioned earlier neither /etc/profile.d/ nor /etc/environment approach worked.
UPDATE:
As I understand now, it is not possible to change environment variables in a running container due to reasons explained in #tgogos answer. However I don't believe this is an issue in my case since after Packer is done provisioning the image, it commits it and uploads to Docker Hub. More accurate example would be as follows:
$ docker run -itd --name test centos:6
$ docker exec -it test /bin/bash
[root#006a9c3195b6 /]# echo 'echo SUCCESS' > /root/test.sh
[root#006a9c3195b6 /]# chmod +x /root/test.sh
[root#006a9c3195b6 /]# echo 'export PATH=/root:$PATH' > /etc/profile.d/my_settings.sh
[root#006a9c3195b6 /]# echo 'PATH=/root:$PATH' > /etc/environment
[root#006a9c3195b6 /]# exit
$ docker commit test test-image:1
$ docker exec -it test-image:1 test.sh
Expecting to see SUCCESS printed but getting
OCI runtime exec failed: exec failed: container_linux.go:296: starting container process caused "exec: \"test.sh\": executable file not found in $PATH": unknown
UPDATE 2
I have updated PATH in ~/.bashrc which lets me execute following:
$ docker run -it test-image:1 /bin/bash
[root#8f821c7b9b82 /]# test.sh
SUCCESS
However running docker run -it test-image:1 test.sh still results in
docker: Error response from daemon: OCI runtime create failed: container_linux.go:296: ...
I can confirm that my image CMD is set to "/bin/bash". So can someone explain why running docker run -it test-image:1 test.sh doesn't source ~/.bashrc?

A few good points are mentioned at:
How to set an environment variable in a running docker container (also check the link to the relevant github issue).
and Docker - Updating Environment Variables of a Container
where #BMitch mentions:
Destroy your container and start a new one up with the new environment variable using docker run -e .... It's identical to changing an environment variable on a running process, you stop it and restart with a new value passed in.
and in the comments section, he adds:
Docker doesn't provide a way to modify an environment variable in a running container because the OS doesn't provide a way to modify an environment variable in a running process. You need to destroy and recreate.
update: (see the comments section)
You can use
docker commit --change "ENV PATH=your_new_path_here" test test-image:1

/etc/profile is only read by bash when invoked by a login shell.
For more information about which files are read by bash on startup see this article.
EDIT: If you change the last line in your example to:
docker exec -it test bash -lc test.sh it works as you expect.

Related

docker exec -> permission denied when executing through ssh

I am trying to execute a command on a docker container that is running in a remote server. I am running most commands through ssh and they all work correctly. However, this command modifies the file /etc/environment and I get a "permission denied" error.
The command in question is docker exec container_id echo 'WDS_SOCKET_PORT=XXXXX' >> /etc/environment
If I run the command from the docker host, it works
If I run a simple command remotely using ssh user#ip docker exec container_id ls, it works
If I run this command remotely using ssh user#ip docker exec container_id echo 'WDS_SOCKET_PORT=XXXXX' >> /etc/environment I get sh: 1: cannot create /etc/environment: Permission denied
I tried adding the option -u 0 to the docker exec command with no luck.
I don't mind making changes to the Dockerfile since I can kill, remove or recreate this container with no problem.
The error isn't coming from docker or ssh, it's coming from your shell that parses the command you want to run. You are trying to modify the file on your host. To do io redirection inside the container, you need to run a shell there and parse the command with that shell.
ssh user#ip "docker exec container_id /bin/sh -c 'echo \"WDS_SOCKET_PORT=XXXXX\" >> /etc/environment'"
EDIT: Note that the whole docker command should be surrounded by quotes. I believe this is because ssh might otherwise parse different parts of the command as parameters of the docker command. This way, each sub-command is clearly delimited.

Executing a script inside a docker container gives no errors but does not work either

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.

OCI runtime exec failed: exec failed: (...) executable file not found in $PATH": unknown

I have dockerized an app which has ffmpeg installed in it via libav-tools. The app launches without problem, yet the problem occured when fluent-ffmpeg npm module tried to execute ffmpeg command, which was not found. When I wanted to check the version of the ffmpeg and the linux distro set up in the image, I used sudo docker exec -it c44f29d30753 "lsb_release -a" command, but it gave the following error: OCI runtime exec failed: exec failed: container_linux.go:296: starting container process caused "exec: \"lsb_release -a\": executable file not found in $PATH": unknown
Then I realized that it gives me the same error with all the commands that I try to run inside the image or the container.
OCI runtime exec failed: exec failed: container_linux.go:296: starting container process caused "exec: \"ffmpeg -a\": executable file not found in $PATH": unknown
This is my Dockerfile:
FROM ubuntu:xenial
FROM node
RUN apt-get -y update
RUN apt-get --yes install libav-tools
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
RUN npm install
COPY . /usr/src/app
RUN npm run build
ENV NODE_ENV production
EXPOSE 8000
CMD ["npm", "run", "start:prod"]
I would kindly ask for your help. Thank you very much!
This happened to me on windows. See below for any of the commands that match your case.
NOTE
You will need to run the commands that match your case below using the correct shell in your container i.e. /bin/bash or /bin/sh. Using sh instead of bash or vice versa will also give you this error. So, confirm that you are using the right shell, or just try both shells and see the one that works.
For these examples, I will be using sh
On Windows CMD (not switching to bash):
docker exec -it <container-id> /bin/sh
On Windows CMD (after switching to bash):
docker exec -it <container-id> //bin//sh
or
winpty docker exec -it <container-id> //bin//sh
On Git Bash:
winpty docker exec -it <container-id> //bin//sh
For Windows users, the reason is documented in the ReleaseNotes file of Git and it is well explained here - Bash in Git for Windows: Weirdness... :
The cause is to do with trying to ensure that posix paths end up being
passed to the git utilities properly. For this reason, Git for Windows
includes a modified MSYS layer that affects command arguments.
Linux
docker exec -it <container-id> /bin/sh
docker exec -it <containerId> sh
I had this due to a simple ordering mistake on my end. I called
[WRONG] docker run <image> <arguments> <command>
When I should have used
docker run <arguments> <image> <command>
Same resolution on similar question: https://stackoverflow.com/a/50762266/6278
If #papigee does solution doesn't work, maybe you don't have the permissions.
I tried #papigee solution but does't work without sudo.
I did :
sudo docker exec -it <container id or name> /bin/sh
Get rid of your quotes around your command. When you quote it, docker tries to run the full string "lsb_release -a" as a command, which doesn't exist. Instead, you want to run the command lsb_release with an argument -a, and no quotes.
sudo docker exec -it c44f29d30753 lsb_release -a
Note, everything after the container name is the command and arguments to run inside the container, docker will not process any of that as options to the docker command.
For others with this error, the debugging steps I'd recommend:
Verify the order of your arguments. Everything after the container name/id is a command to run. So you don't want docker exec $cid -it /bin/sh because that will try to run the command -it in the $cid container. Instead you want docker exec -it $cid /bin/sh
Look at the command that is failing, everything in the quotes after the exec error (e.g. lsb_release -a in "exec: \"lsb_release -a\") is the binary trying to be run. Make sure that binary exists in your image. E.g. if you are using alpine or busybox, bash may not exist, but /bin/sh does. And that binary is the full string, e.g. you would be able to run something like ls "/usr/bin/lsb_release -a" and see a file with the space and -a in the filename.
If you're using Windows with Git bash and see a long path prefixed on that command trying to be run, that's Git bash trying to do some automatic conversions of /path/to/binary, you can disable that by doubling the first slash, e.g. //bin/sh.
If the command you're running is a script in the container, check the first line of that script, containing the #!/path/to/interpreter, make sure that interpreter exists in the image, at that path, and that the script is saved with linux linefeeds (lf, not cr+lf, you won't want the \r showing in the file when read in linux because that becomes part of the command it's looking to execute).
If you don't have a full path to the binary in the command you're running, check the value of $PATH in the image, and verify the binary exists within one of those directories. E.g. you can docker exec -it $cid /bin/sh and echo $PATH and type some_command to verify some_command is found in your path.
If your command is not an executable, but rather a shell builtin, you'll need to execute it with a shell instead of directly. That can be done with docker exec -it $cid /bin/sh -c "your_shell_builtin"
I solved this with this commands:
Run the container:
docker run -d <image-name>
List containers:
docker ps -a
Use the container ID:
docker exec -it <container-id> /bin/sh
I was running into this issue and it turned out that I needed to do this:
docker run ${image_name} bash -c "${command}"
You can use another shell to execute the same command:
Error I get when i execute:
[jenkins#localhost jenkins_data]$ docker exec -it mysqldb \bin\bash
OCI runtime exec failed: exec failed: container_linux.go:345: starting container process caused "exec: \"binsh\": executable file not found in $PATH": unknown
Solution:
When I execute it with below command, using bash shell it works:
[jenkins#localhost jenkins_data]$ docker exec -it mysqldb bash
root#<container-ID>:/#
What I did to solve was simply:
Run docker ps -a
Check for the command of the container (mine started with /bin/sh)
Run docker-compose exec < name_of_service > /bin/sh (if that is what started your command
This is for solving when using docker compose
I was running a container in a docker-compose.
entrypoint:
- ls
worked, but
entrypoint:
- ls tests
did not.
It's because the arguments have to be on separate lines.. 🤦‍♂
entrypoint:
- ls
- tests
This has happened to me. My issue was caused when I didn't mount Docker file system correctly, so I configured the Disk Image Location and re-bind File sharing mount, and this now worked correctly.
For reference, I use Docker Desktop in Windows.
In my case i saved the docker image and instead of load-ing it on the other machine i imported it which are very different and lead me to an error similar to this.
you have to run like below:
docker exec sh -c 'echo "$ENV_NAME"'
I had windows line endings in a shell script. change to LF dos2unix
If you got this error when using the docker run command, you may have made a simple syntax error.
Example
Incorrect:
docker run myimage -p 3838:3838
docker: Error response from daemon: failed to create shim: OCI runtime create
failed: container_linux.go:380: starting container process caused:
exec: "-p": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
Correct (options go before image name):
docker run -p 3838:3838 myimage

set environment variable in running docker contianer

I need to set environment variable in a running docker container. I am already aware of the way of setting environment variable while creating a container. As far I found there is no available straight forward way to do this with docker and docker is planning to add something with new version 1.13.
But I found that some people able to manage it which is not working for me now. I tried following ways but did not work for me-
docker exec -it -u=root test /bin/bash -c "export port=8090"
echo "export port=8090" to /etc/bash.bashrc using a script and then source it
docker exec -it test /bin/bash -c "source /etc/bash.bashrc"
configuring the whole thing in a script and run it from host also did not work. While running script from host all the other command successfully executes except "export port=8090" or "source /etc/bash.bashrc" or "source /root/.bashrc".
Can anyone explain why sourcing file from host does not work in docker container even when I set user("-u=root")? Can anyone help me to solve this? When I source the file from inside the container it works perfectly. But in my case I have to do it from host machine
NOTE:, I am using docker 1.12 and tried the above in ubuntu:16.04 and ubuntu:14.04
If you have a running process in the docker and you are attempting to change the environment variable in the docker so the running process will dynamically change - this will not work. The environment variables of a process are set when it starts. You can see here ways to overcome that, but I don't think that is the right way to go.
I would instead, have a configuration file that the file reads (or listens to) periodically. And when you want to change the configuration change the file.
If this isn't your scenario, please describe your scenario so we can better assist you.
I find a way to provide environment variable to a running container. Fist upgrade your docker-engine. I am using V1.12.5.
create a script with environment variables-
#!/bin/bash
echo "export VAR1=VAL1
export VAR2=VAL2" >> /etc/bash.bashrc
source /etc/bash.bashrc
Now start a container. Here, 'test' is the container name:
docker run -idt --name=test ubuntu
Copy your script to container:
docker cp script.sh test:/
Run the script :
docker exec -it test /bin/bash -c "/script.sh"
Restart your container:
docker restart test
Go to container shell
docker exec -it test /bin/bash
Check the variable
echo $VAR1

Docker Exec command does not work properly

I have a script run.sh that I run as I initialize the container through docker run command. The script runs successfully. I can also get a bash instance (through docker exec -i -t container-name bash) in the container and run the script successfully (note that by default I have su privileges when I get the bash).
However, when I run the script from the host through docker exec -i -t container-name /run.sh the script runs but does not provide the outcome that it provides through the alternative approaches. I know it runs as it produces some of the expected behavior but not all of them. So my main question is what are the difference between executing a script through commandline and running the same script through docker exec.

Resources