How to pass a command to a docker container with PowerShell? - docker

I would like to send a command to an already existing docker container.
I am forced to do it via powershell or CMD, git bash not giving the correct Windows path using pwd.
Functionnal example
$cur_path = $pwd.Path
$container_id = docker run -it -d --volume $cur_path\:/matmuttools saagie/python:3.5.2-1.3.1-centos
docker exec $container_id 'ls'
docker stop $container_id
docker rm $container_id
Gives the following output:
anaconda-post.log
bin
dev
etc
git-credential-manager-2.0.4.jar
home
lib
lib64
lost+found
matmuttools
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
Non functionnal example
However, when doing something more "complex", docker throws an error:
$cur_path = $pwd.Path
$container_id = docker run -it -d --volume $cur_path\:/matmuttools saagie/python:3.5.2-1.3.1-centos
docker exec $container_id 'ls /matmuttools'
docker stop $container_id
docker rm $container_id
Throws the following error:
OCI runtime exec failed: exec failed: container_linux.go:367: starting
container process caused: exec: "ls /matmuttools": stat ls
/matmuttools: no such file or directory: unknown
If I pass ls without quotes and without more argument (just ls), it runs in the container. If I pass ls without quotes and with arguments, it runs on the host.
Runs in the container:
docker exec $container_id ls
Runs on the host:
docker exec $container_id ls /
How do I properly send a command to execute to a docker container in powershell (or with CMD) ?

In git bash, to get the actual windows path, use:
pwd -W
Now that I do not need powershell anymore (I am pretty sure it was not a blocking thing, but anyway):
docker exec -it frosty_lamport bash -c "cd /matmuttools; ls"

Related

Change selected directory at startup of docker container

Is it possible to save the selected directory in docker before exiting the container?
As a default, docker does not remember the selected directory before it exits.
In the example below, I changed the directory inside docker to home.
Example:
> docker exec -it loving_mccarthy /bin/bash
root#6bd70522dd17:/# cd /home
root#6bd70522dd17:/home# exit
exit
> docker exec -it loving_mccarthy /bin/bash
/#
You can achieve this behavior by setting up a bash function, which you can configure to run on terminal exit, that writes the current working directory to the .bashrc file, which you can then use the second time you run a bash terminal in the container with cd -.
Here's a full example:
Start the container:
$ docker run -it --name=example -d ubuntu /bin/bash
Run docker exec the first time, and configure the function for trap:
$ docker exec -it example /bin/bash
root#ecfc612fe6b8:/# set_workdir_on_exit() { echo "export OLDPWD=$PWD" >> $HOME/.bashrc ;}
root#ecfc612fe6b8:/# trap 'set_workdir_on_exit' EXIT
root#ecfc612fe6b8:/# cd /home
root#ecfc612fe6b8:/home# exit
Run docker exec the second time:
$ docker exec -it example /bin/bash
root#6a491ad1aee5:/# cd -
/home
root#6a491ad1aee5:/home#

Why does 'docker run -t' redirect stderr to stdout?

From docker run --help:
-t, --tty Allocate a pseudo-TTY
Very nice. I use that to get color output automatically. The problem is, it also redirects stderr to stdout.
Without -t, stderr isn't redirected, which is what I want:
$ docker run ubuntu ls /aaaaaa
ls: cannot access '/aaaaaa': No such file or directory
$ docker run ubuntu ls /aaaaaa 2> /dev/null
With -t, the error messages are redirected to stdout:
$ docker run -t ubuntu ls /aaaaaa
ls: cannot access '/aaaaaa': No such file or directory
$ docker run -t ubuntu ls /aaaaaa 2> /dev/null
ls: cannot access '/aaaaaa': No such file or directory
$ docker run -t ubuntu ls /aaaaaa > /dev/null
Why is that? Is there a way to still allocate a pseudo-TTY and keep stderr separate?
e.g. I want to run something like this in CI:
docker run ... my-command > out.json
while the logger shows warnings and error messages in color.
You need to give your command a shell session so your container can have its own output redirection and not rely on what docker runtime has setup.
This will print error message as usual:
docker run -t --rm busybox sh -c "ls /aaa"
This will not print error message to your allocated tty:
docker run -t --rm busybox sh -c "ls /aaa 2>/dev/null"
This will print the directory listing of /etc:
docker run -t --rm busybox sh -c "ls /etc 2>/dev/null"

Command sent to docker container shell exec failed

I am launching a container to issue some command on the host machine files.
This is done via a shell script:
echo "--- Starting container"
container_id=$(docker run -d -it --mount type=bind,source="$mount_path",target=/usr/share --name project-test python:3.5.2-alpine)
docker exec $container_id /bin/sh -c "cd /usr/share && pwd && ls -l"
However this throws an error that I do not understand how to fix:
OCI runtime exec failed: exec failed: container_linux.go:367: starting
container process caused: exec: "C:/Program Files/Git/usr/bin/sh":
stat C:/Program Files/Git/usr/bin/sh: no such file or directory:
unknown
My host machine is a windows 10. From my little understanding, the exec command on the container should opperate inside the container. But the error shows path from my host machine. Why is that ? How to properly send a command to a docker container ?
Edit:
The logs of the container after the docker exec are:
Python 3.5.2 (default, Dec 27 2016, 21:33:11)
[GCC 5.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
Edit: result of the command issued manually (expected result)
/ # cd /usr/share && pwd && ls -l
/usr/share
total 5
-rwxr-xr-x 1 root root 347 May 20 06:31 README.md
drwxrwxrwx 1 root root 4096 May 20 08:22 myproject
docker exec $container_id ls -l /usr/share
ls: C:/Program Files/Git/usr/share: No such file or directory
Your acquisition of container_id is maybe wrong. Ensure the value is correctly set in this variable before continuing.
Just a note before: you're using -d and -it options simultaneously. The -it is ignored since you tell the container to run as a daemon, you won't attach your TTY to it. The -it options are totally ignored here.
When you exec into a container, it runs a new session in the container. It means you won't see the result of the command you give in the logs since it's in the output of the new session.
To get access to the logs, you must use -it options when using exec. If you refer to #nish8690 on the question Docker exec in docker windows, you'll need to double your slashes in the command:
instead of
docker exec -it [containerid] /bin/sh
try to use
docker exec -it [containerid] //bin//sh
-- #nish8690, Docker exec in docker windows
Resulting maybe in:
docker exec -it $container_id //bin//sh -c "cd /usr/share && pwd && ls -l"
While using docker from a Windows host, the slash is converted to windows slash so the git is confusing.
To access a docker machine from a Windows host, you most to override the windows slash format by using double slash instead.
an example how to run a file, instead of running /run.sh you need to run //run.sh.
This solution will solve your problem.

how to ssh docker container

I am running the container hypriot/rpi-busybox-httpd
I am trying to ssh to docker container: but it is giving error :
pi#raspberrypi:~ $ docker exec -it cc55da85b915 bash
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"bash\": executable file not found in $PATH"
pi#raspberrypi:~ $ docker exec -it cc55da85b915 sh
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"sh\": executable file not found in $PATH"
am I doing the right away ?
It could be your image does not have the binary /bin/bash installed (as suggested before), I had the same problem and I was able to enter into the container using /bin/sh
docker exec -ti cc55da85b915 /bin/sh
Another workaround could be execute directly the commands without get access to any shell.
docker exec -ti cc55da85b915 ls /etc
The image you're using seems that it doesn't have the binary /bin/bash installed but it should have /bin/sh
Try:
docker exec -it cc55da85b915 sh
You might need to specify the full path to bash, e.g.:
docker exec -it cc55da85b915 /bin/bash
or /usr/local/bin/bash, or wherever bash is located in that image.
Hope this helps!
You have many different ways to do that, you can attach using docker's attach command.
$ sudo docker attach cc55da85b915 #by ID
Or you can use docker exec command:
$ sudo docker exec -i -t cc55da85b915 /bin/bash
If /bin/bash fails, you can use /bin/sh that works in more containers:
$ sudo docker exec -i -t cc55da85b915 /bin/sh
if you are still looking for an answer. This worked for me on windows.
winpty docker exec -it <containerid> sh
For Alpine based image, docker exec -ti cc55da85b915 /bin/sh and docker exec -ti cc55da85b915 ls /etc worked. As suggested by 'Esteban Collado'.
However for other Linux versions I use,
docker exec -ti cc55da85b915 bash
Try Below Command:
docker exec -it cc55da85b915 /bin/busybox sh
To list all the available commands use:
docker exec -it cc55da85b915 /bin/busybox --list
This will also relevant for Kubernetes pods.
For example if you'll try to connect to a pod which doesn't contain the shell you specified:
kubectl exec -it some-busybox-pod bash
(busybox have sh on it not bash).
You'll end up with the same error:
OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown
command terminated with exit code 126

How to take Oracle-xe-11g backup from running Docker container

I am running oracle-xe-11g on rancher os. I want to take the data backup of my DB. When I tried with the command
docker exec -it $Container_Name /bin/bash
then I entered:
exp userid=username/password file=test.dmp
It is working fine, and it created the test.dump file.
But I want to run the command with the docker exec command itself. When I tried this command:
docker exec $Container_Name sh -C exp userid=username/password file=test.dmp
I am getting this error message: sh: 0: Can't open exp.
The problem is:
When running bash with -c switch it is not running as interactive or a login shell so bash won't read the same startup scripts. Anything set in /etc/profile, ~/.bash_profile, ~/.bash_login, or ~/.profile would be skipped.
Workaround:
run your container with following command:
sudo docker run -d --name Oracle-DB -p 49160:22 -p 1521:1521 -e ORACLE_ALLOW_REMOTE=true -e ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe -e PATH=/u01/app/oracle/product/11.2.0/xe/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -e ORACLE_SID=XE -e SHLVL=1 wnameless/oracle-xe-11g
What I'm doing is specifying the environment variables set in the container using docker.
Now for generating the backup file:
sudo docker exec -it e0e6a0d3e6a9 /bin/bash -c "exp userid=system/oracle file=/test.dmp"
Please note the file will be created inside the container, so you need to copy it to docker host via docker cp command
This is how I did it. Mount a volume to the container e.g. /share/backups/ then execute:
docker exec -it oracle /bin/bash -c "ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe ORACLE_SID=XE /u01/app/oracle/product/11.2.0/xe/bin/exp userid=<username>/<password> owner=<owner> file=/share/backups/$(date +"%Y%m%d")_backup.dmp"

Resources