Related
I've noticed with docker that I need to understand what's happening inside a container or what files exist in there. One example is downloading images from the docker index - you don't have a clue what the image contains so it's impossible to start the application.
What would be ideal is to be able to ssh into them or equivalent. Is there a tool to do this, or is my conceptualisation of docker wrong in thinking I should be able to do this.
Here are a couple different methods...
A) Use docker exec (easiest)
Docker version 1.3 or newer supports the command exec that behave similar to nsenter. This command can run new process in already running container (container must have PID 1 process running already). You can run /bin/bash to explore container state:
docker exec -t -i mycontainer /bin/bash
see Docker command line documentation
B) Use Snapshotting
You can evaluate container filesystem this way:
# find ID of your running container:
docker ps
# create image (snapshot) from container filesystem
docker commit 12345678904b5 mysnapshot
# explore this filesystem using bash (for example)
docker run -t -i mysnapshot /bin/bash
This way, you can evaluate filesystem of the running container in the precise time moment. Container is still running, no future changes are included.
You can later delete snapshot using (filesystem of the running container is not affected!):
docker rmi mysnapshot
C) Use ssh
If you need continuous access, you can install sshd to your container and run the sshd daemon:
docker run -d -p 22 mysnapshot /usr/sbin/sshd -D
# you need to find out which port to connect:
docker ps
This way, you can run your app using ssh (connect and execute what you want).
D) Use nsenter
Use nsenter, see Why you don't need to run SSHd in your Docker containers
The short version is: with nsenter, you can get a shell into an
existing container, even if that container doesn’t run SSH or any kind
of special-purpose daemon
UPDATE: EXPLORING!
This command should let you explore a running docker container:
docker exec -it name-of-container bash
The equivalent for this in docker-compose would be:
docker-compose exec web bash
(web is the name-of-service in this case and it has tty by default.)
Once you are inside do:
ls -lsa
or any other bash command like:
cd ..
This command should let you explore a docker image:
docker run --rm -it --entrypoint=/bin/bash name-of-image
once inside do:
ls -lsa
or any other bash command like:
cd ..
The -it stands for interactive... and tty.
This command should let you inspect a running docker container or image:
docker inspect name-of-container-or-image
You might want to do this and find out if there is any bash or sh in there. Look for entrypoint or cmd in the json return.
NOTE: This answer relies on commen tool being present, but if there is no bash shell or common tools like ls present you could first add one in a layer if you have access to the Dockerfile:
example for alpine:
RUN apk add --no-cache bash
Otherwise if you don't have access to the Dockerfile then just copy the files out of a newly created container and look trough them by doing:
docker create <image> # returns container ID the container is never started.
docker cp <container ID>:<source_path> <destination_path>
docker rm <container ID>
cd <destination_path> && ls -lsah
see docker exec documentation
see docker-compose exec documentation
see docker inspect documentation
see docker create documentation
In case your container is stopped or doesn't have a shell (e.g. hello-world mentioned in the installation guide, or non-alpine traefik), this is probably the only possible method of exploring the filesystem.
You may archive your container's filesystem into tar file:
docker export adoring_kowalevski > contents.tar
Or list the files:
docker export adoring_kowalevski | tar t
Do note, that depending on the image, it might take some time and disk space.
Before Container Creation :
If you to explore the structure of the image that is mounted inside the container you can do
sudo docker image save image_name > image.tar
tar -xvf image.tar
This would give you the visibility of all the layers of an image and its configuration which is present in json files.
After container creation :
For this there are already lot of answers above. my preferred way to do
this would be -
docker exec -t -i container /bin/bash
The most upvoted answer is working for me when the container is actually started, but when it isn't possible to run and you for example want to copy files from the container this has saved me before:
docker cp <container-name>:<path/inside/container> <path/on/host/>
Thanks to docker cp (link) you can copy directly from the container as it was any other part of your filesystem.
For example, recovering all files inside a container:
mkdir /tmp/container_temp
docker cp example_container:/ /tmp/container_temp/
Note that you don't need to specify that you want to copy recursively.
The file system of the container is in the data folder of docker, normally in /var/lib/docker. In order to start and inspect a running containers file system do the following:
hash=$(docker run busybox)
cd /var/lib/docker/aufs/mnt/$hash
And now the current working directory is the root of the container.
you can use dive to view the image content interactively with TUI
https://github.com/wagoodman/dive
Try using
docker exec -it <container-name> /bin/bash
There might be possibility that bash is not implemented. for that you can use
docker exec -it <container-name> sh
On Ubuntu 14.04 running Docker 1.3.1, I found the container root filesystem on the host machine in the following directory:
/var/lib/docker/devicemapper/mnt/<container id>/rootfs/
Full Docker version information:
Client version: 1.3.1
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): 4e9bbfa
OS/Arch (client): linux/amd64
Server version: 1.3.1
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): 4e9bbfa
In my case no shell was supported in container except sh. So, this worked like a charm
docker exec -it <container-name> sh
I use another dirty trick that is aufs/devicemapper agnostic.
I look at the command that the container is running e.g. docker ps
and if it's an apache or java i just do the following:
sudo -s
cd /proc/$(pgrep java)/root/
and voilá you're inside the container.
Basically you can as root cd into /proc/<PID>/root/ folder as long as that process is run by the container. Beware symlinks will not make sense wile using that mode.
The most voted answer is good except if your container isn't an actual Linux system.
Many containers (especially the go based ones) don't have any standard binary (no /bin/bash or /bin/sh). In that case, you will need to access the actual containers file directly:
Works like a charm:
name=<name>
dockerId=$(docker inspect -f {{.Id}} $name)
mountId=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$dockerId/mount-id)
cd /var/lib/docker/aufs/mnt/$mountId
Note: You need to run it as root.
Only for LINUX
The most simple way that I use was using proc dir, the container must be running in order to inspect the docker container files.
Find out the process id (PID) of the container and store it into some variable
PID=$(docker inspect -f '{{.State.Pid}}' your-container-name-here)
Make sure the container process is running, and use the variable name to get into the container folder
cd /proc/$PID/root
If you want to get through the dir without finding out the PID number, just use this long command
cd /proc/$(docker inspect -f '{{.State.Pid}}' your-container-name-here)/root
Tips:
After you get inside the container, everything you do will affect the actual process of the container, such as stopping the service or changing the port number.
Hope it helps
Note:
This method only works if the container is still running, otherwise, the directory wouldn't exist anymore if the container has stopped or removed
None of the existing answers address the case of a container that exited (and can't be restarted) and/or doesn't have any shell installed (e.g. distroless ones). This one works as long has you have root access to the Docker host.
For a real manual inspection, find out the layer IDs first:
docker inspect my-container | jq '.[0].GraphDriver.Data'
In the output, you should see something like
"MergedDir": "/var/lib/docker/overlay2/03e8df748fab9526594cfdd0b6cf9f4b5160197e98fe580df0d36f19830308d9/merged"
Navigate into this folder (as root) to find the current visible state of the container filesystem.
This will launch a bash session for the image:
docker run --rm -it --entrypoint=/bin/bash
On newer versions of Docker you can run docker exec [container_name] which runs a shell inside your container
So to get a list of all the files in a container just run docker exec [container_name] ls
I wanted to do this, but I was unable to exec into my container as it had stopped and wasn't starting up again due to some error in my code.
What worked for me was to simply copy the contents of the entire container into a new folder like this:
docker cp container_name:/app/ new_dummy_folder
I was then able to explore the contents of this folder as one would do with a normal folder.
For me, this one works well (thanks to the last comments for pointing out the directory /var/lib/docker/):
chroot /var/lib/docker/containers/2465790aa2c4*/root/
Here, 2465790aa2c4 is the short ID of the running container (as displayed by docker ps), followed by a star.
For docker aufs driver:
The script will find the container root dir(Test on docker 1.7.1 and 1.10.3 )
if [ -z "$1" ] ; then
echo 'docker-find-root $container_id_or_name '
exit 1
fi
CID=$(docker inspect --format {{.Id}} $1)
if [ -n "$CID" ] ; then
if [ -f /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id ] ; then
F1=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id)
d1=/var/lib/docker/aufs/mnt/$F1
fi
if [ ! -d "$d1" ] ; then
d1=/var/lib/docker/aufs/diff/$CID
fi
echo $d1
fi
This answer will help those (like myself) who want to explore the docker volume filesystem even if the container isn't running.
List running docker containers:
docker ps
=> CONTAINER ID "4c721f1985bd"
Look at the docker volume mount points on your local physical machine (https://docs.docker.com/engine/tutorials/dockervolumes/):
docker inspect -f {{.Mounts}} 4c721f1985bd
=> [{ /tmp/container-garren /tmp true rprivate}]
This tells me that the local physical machine directory /tmp/container-garren is mapped to the /tmp docker volume destination.
Knowing the local physical machine directory (/tmp/container-garren) means I can explore the filesystem whether or not the docker container is running. This was critical to helping me figure out that there was some residual data that shouldn't have persisted even after the container was not running.
If you are using Docker v19.03, you follow the below steps.
# find ID of your running container:
docker ps
# create image (snapshot) from container filesystem
docker commit 12345678904b5 mysnapshot
# explore this filesystem
docker run -t -i mysnapshot /bin/sh
For an already running container, you can do:
dockerId=$(docker inspect -f {{.Id}} [docker_id_or_name])
cd /var/lib/docker/btrfs/subvolumes/$dockerId
You need to be root in order to cd into that dir. If you are not root, try 'sudo su' before running the command.
Edit: Following v1.3, see Jiri's answer - it is better.
another trick is to use the atomic tool to do something like:
mkdir -p /path/to/mnt && atomic mount IMAGE /path/to/mnt
The Docker image will be mounted to /path/to/mnt for you to inspect it.
My preferred way to understand what is going on inside container is:
expose -p 8000
docker run -it -p 8000:8000 image
Start server inside it
python -m SimpleHTTPServer
If you are using the AUFS storage driver, you can use my docker-layer script to find any container's filesystem root (mnt) and readwrite layer :
# docker-layer musing_wiles
rw layer : /var/lib/docker/aufs/diff/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f
mnt : /var/lib/docker/aufs/mnt/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f
Edit 2018-03-28 :
docker-layer has been replaced by docker-backup
The docker exec command to run a command in a running container can help in multiple cases.
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
Options:
-d, --detach Detached mode: run command in the background
--detach-keys string Override the key sequence for detaching a
container
-e, --env list Set environment variables
-i, --interactive Keep STDIN open even if not attached
--privileged Give extended privileges to the command
-t, --tty Allocate a pseudo-TTY
-u, --user string Username or UID (format:
[:])
-w, --workdir string Working directory inside the container
For example :
1) Accessing in bash to the running container filesystem :
docker exec -it containerId bash
2) Accessing in bash to the running container filesystem as root to be able to have required rights :
docker exec -it -u root containerId bash
This is particularly useful to be able to do some processing as root in a container.
3) Accessing in bash to the running container filesystem with a specific working directory :
docker exec -it -w /var/lib containerId bash
Often times I only need to explore the docker filesystem because my build won't run, so docker run -it <container_name> bash is impractical. I also do not want to waste time and memory copying filesystems, so docker cp <container_name>:<path> <target_path> is impractical too.
While possibly unorthodox, I recommend re-building with ls as the final command in the Dockerfile:
CMD [ "ls", "-R" ]
I've found the easiest, all-in-one solution to View, Edit, Copy files with a GUI app inside almost any running container.
mc editing files in docker
inside the container install mc and ssh: docker exec -it <container> /bin/bash, then with prompt install mc and ssh packages
in same exec-bash console, run mc
press ESC then 9 then ENTER to open menu and select "Shell link..."
using "Shell link..." open SCP-based filesystem access to any host with ssh server running (including the one running docker) by it's IP address
do your job in graphical UI
this method overcomes all issues with permissions, snap isolation etc., allows to copy directly to any machine and is the most pleasant to use for me
I had an unknown container, that was doing some production workload and did not want to run any command.
So, I used docker diff.
This will list all files that the container had changed and therefore good suited to explore the container file system.
To get only a folder you can just use grep:
docker diff <container> | grep /var/log
It will not show files from the docker image. Depending on your use case this can help or not.
Late to the party, but in 2022 we have VS Code
I'm getting started working with Docker. I'm using the WordPress base image and docker-compose.
I'm trying to ssh into one of the containers to inspect the files/directories that were created during the initial build. I tried to run docker-compose run containername ls -la, but that didn't do anything. Even if it did, I'd rather have a console where I can traverse the directory structure, rather than run a single command. What is the right way to do this with Docker?
docker attach will let you connect to your Docker container, but this isn't really the same thing as ssh. If your container is running a webserver, for example, docker attach will probably connect you to the stdout of the web server process. It won't necessarily give you a shell.
The docker exec command is probably what you are looking for; this will let you run arbitrary commands inside an existing container. For example:
docker exec -it <mycontainer> bash
Of course, whatever command you are running must exist in the container filesystem.
In the above command <mycontainer> is the name or ID of the target container. It doesn't matter whether or not you're using docker compose; just run docker ps and use either the ID (a hexadecimal string displayed in the first column) or the name (displayed in the final column). E.g., given:
$ docker ps
d2d4a89aaee9 larsks/mini-httpd "mini_httpd -d /cont 7 days ago Up 7 days web
I can run:
$ docker exec -it web ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
18: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:3/64 scope link
valid_lft forever preferred_lft forever
I could accomplish the same thing by running:
$ docker exec -it d2d4a89aaee9 ip addr
Similarly, I could start a shell in the container;
$ docker exec -it web sh
/ # echo This is inside the container.
This is inside the container.
/ # exit
$
To bash into a running container, type this:
docker exec -t -i container_name /bin/bash
or
docker exec -ti container_name /bin/bash
or
docker exec -ti container_name sh
Historical note: At the time I wrote this answer, the title of the question was: "How to ssh into a docker container?"
As other answers have demonstrated, it is common to execute and interact with preinstalled commands (including shells) in a locally-accessible running container using docker exec, rather than SSH:
docker exec -it (container) (command)
Note: The below answer is based on Ubuntu (of 2016). Some translation of the installation process will be required for non-Debian containers.
Let's say, for reasons that are your own, you really do want to use SSH. It takes a few steps, but it can be done. Here are the commands that you would run inside the container to set it up...
apt-get update
apt-get install openssh-server
mkdir /var/run/sshd
chmod 0755 /var/run/sshd
/usr/sbin/sshd
useradd --create-home --shell /bin/bash --groups sudo username ## includes 'sudo'
passwd username ## Enter a password
apt-get install x11-apps ## X11 demo applications (optional)
ifconfig | awk '/inet addr/{print substr($2,6)}' ## Display IP address (optional)
Now you can even run graphical applications (if they are installed in the container) using X11 forwarding to the SSH client:
ssh -X username#IPADDRESS
xeyes ## run an X11 demo app in the client
Here are some related resources:
openssh-server doesn't start in Docker container
How to get bash or ssh into a running container in background mode?
Can you run GUI applications in a Linux Docker container?
Other useful approaches for graphical access found with search: Docker X11
If you run SSHD in your Docker containers, you're doing it wrong!
If you're here looking for a Docker Compose-specific answer like I was, it provides an easy way in without having to look up the generated container ID.
docker-compose exec takes the name of the service as per your docker-compose.yml file.
So to get a Bash shell for your 'web' service, you can do:
$ docker-compose exec web bash
If the container has already exited (maybe due to some error), you can do
$ docker run --rm -it --entrypoint /bin/ash image_name
or
$ docker run --rm -it --entrypoint /bin/sh image_name
or
$ docker run --rm -it --entrypoint /bin/bash image_name
to create a new container and get a shell into it. Since you specified --rm, the container would be deleted when you exit the shell.
Notice: this answer promotes a tool I've written.
I've created a containerized SSH server that you can 'stick' to any running container. This way you can create compositions with every container. The only requirement is that the container has Bash.
The following example would start an SSH server attached to a container with name 'my-container'.
docker run -d -p 2222:22 \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CONTAINER=my-container -e AUTH_MECHANISM=noAuth \
jeroenpeeters/docker-ssh
ssh localhost -p 2222
When you connect to this SSH service (with your SSH client of choice) a Bash session will be started in the container with name 'my-container'.
For more pointers and documentation see: https://github.com/jeroenpeeters/docker-ssh
Start a session into a Docker container using this command:
sudo docker exec -i -t (container ID) bash
If you're using Docker on Windows and want to get shell access to a container, use this:
winpty docker exec -it <container_id> sh
Most likely, you already have Git Bash installed. If you don't, make sure to install it.
In some cases your image can be Alpine-based. In this case it will throw:
OCI runtime exec failed: exec failed: container_linux.go:348: starting
container process caused "exec: \"bash\": executable file not found in
$PATH": unknown
Because /bin/bash doesn't exist. Instead of this you should use:
docker exec -it 9f7d99aa6625 ash
or
docker exec -it 9f7d99aa6625 sh
To connect to cmd in a Windows container, use
docker exec -it d8c25fde2769 cmd
Where d8c25fde2769 is the container id.
docker exec -it <container_id or name> bash
OR
docker exec -it <container_id or name> /bin/bash
GOINSIDE SOLUTION
install goinside command line tool with:
sudo npm install -g goinside
and go inside a docker container with a proper terminal size with:
goinside docker_container_name
old answer
We've put this snippet in ~/.profile:
goinside(){
docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside
Not only does this make everyone able to get inside a running container with:
goinside containername
It also solves a long lived problem about fixed Docker container terminal sizes. Which is very annoying if you face it.
Also if you follow the link you'll have command completion for your docker container names too.
To inspect files, run docker run -it <image> /bin/sh to get an interactive terminal. The list of images can be obtained by docker images. In contrary to docker exec this solution works also in case when an image doesn't start (or quits immediately after running).
Simple
docker exec -it <container_id> bash
in above -it means interactive terminal.
also, with image name:
docker exec -it <REPOSITORY name> bash
It is simple!
List out all your Docker images:
sudo docker images
On my system it showed the following output:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
bash latest 922b9cc3ea5e 9 hours ago
14.03 MB
ubuntu latest 7feff7652c69 5 weeks ago 81.15 MB
I have two Docker images on my PC. Let's say I want to run the first one.
sudo docker run -i -t ubuntu:latest /bin/bash
This will give you terminal control of the container. Now you can do all type of shell operations inside the container. Like doing ls will output all folders in the root of the file system.
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
I've created a terminal function for easier access to the container's terminal. Maybe it's useful to you guys as well:
So the result is, instead of typing:
docker exec -it [container_id] /bin/bash
you'll write:
dbash [container_id]
Put the following in your ~/.bash_profile (or whatever else that works for you), then open a new terminal window and enjoy the shortcut:
#usage: dbash [container_id]
dbash() {
docker exec -it "$1" /bin/bash
}
2022 Solution
Consider another option
Why do you need it?
There is a bunch of modern docker-images that are based on distroless base images (they don't have /bin/bash either /bin/sh) so it becomes impossible to docker exec -it {container-name} bash into them.
How to shell-in any container
Use opener:
requires to add alias in your environment opener wordpress
works anywhere docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock artemkaxboy/opener wordpress
Instead of wordpress you can use name or id or image-name of any container you want to connect
How it works
Opener is a set of python scripts wrapped-up to a docker image. It finds target container by any unique attribute (name, id, port, image), tries to connect to target using bash. If bash is not found opener tries to connect using sh. Finally if sh is not found either opener installs busybox into target container and connects to the target using busybox shell, opener deletes busybox during disconnection.
$ docker exec -it <Container-Id> /bin/bash
Or depending on the shell, it can be
$ docker exec -it <Container-Id> /bin/sh
You can get the container-Id via docker ps command
-i = interactive
-t = to allocate a psuedo-TTY
you can interact with the terminal in docker container by passing the option -ti
docker run --rm -ti <image-name>
eg: docker run --rm -ti ubuntu
-t stands for terminal
-i stands for interactive
There are at least 2 options depending on the target.
Option 1: Create a new bash process and join into it (easier)
Sample start: docker exec -it <containername> /bin/bash
Quit: type exit
Pro: Does work on all containers (not depending on CMD/Entrypoint)
Contra: Creates a new process with own session and own environment-vars
Option 2: Attach to the already running bash (better)
Sample start: docker attach --detach-keys ctrl-d <containername>
Quit: use keys ctrl and d
Pro: Joins the exact same running bash which is in the container. You have same the session and same environment-vars.
Contra: Only works if CMD/Entrypoint is an interactive bash like CMD ["/bin/bash"] or CMD ["/bin/bash", "--init-file", "myfile.sh"] AND if container has been started with interactive options like docker run -itd <image> (-i=interactive, -t=tty and -d=deamon [opt])
We found option 2 more useful. For example we changed apache2-foreground to a normal background apache2 and started a bash after that.
docker exec will definitely be a solution. An easy way to work with the question you asked is by mounting the directory inside Docker to the local system's directory.
So that you can view the changes in local path instantly.
docker run -v /Users/<path>:/<container path>
Use:
docker attach <container name/id here>
The other way, albeit there is a danger to it, is to use attach, but if you Ctrl + C to exit the session, you will also stop the container. If you just want to see what is happening, use docker logs -f.
:~$ docker attach --help
Usage: docker attach [OPTIONS] CONTAINER
Attach to a running container
Options:
--detach-keys string Override the key sequence for detaching a container
--help Print usage
--no-stdin Do not attach STDIN
--sig-proxy Proxy all received signals to the process (default true)
Use this command:
docker exec -it containerid /bin/bash
To exec into a running container named test, below is the following commands
If the container has bash shell
docker exec -it test /bin/bash
If the container has bourne shell and most of the cases it's present
docker run -it test /bin/sh
If you have Docker installed with Kitematic, you can use the GUI. Open Kitematic from the Docker icon and in the Kitematic window select your container, and then click on the exec icon.
You can see the container log and lots of container information (in settings tab) in this GUI too.
In my case, for some reason(s) I need to check all the network involved information in each container. So the following commands must be valid in a container...
ip
route
netstat
ps
...
I checked through all these answers, none were helpful for me. I’ve searched information in other websites. I won’t add a super link here, since it’s not written in English. So I just put up this post with a summary solution for people who have the same requirements as me.
Say you have one running container named light-test. Follow the steps below.
docker inspect light-test -f {{.NetworkSettings.SandboxKey}}. This command will get reply like /var/run/docker/netns/xxxx.
Then ln -s /var/run/docker/netns/xxxx /var/run/netns/xxxx. The directory may not exist, do mkdir /var/run/netns first.
Now you may execute ip netns exec xxxx ip addr show to explore network world in container.
PS. xxxx is always the same value received from the first command. And of course, any other commands are valid, i.e. ip netns exec xxxx netstat -antp|grep 8080.
There are two options we can connect to the docker terminal directly with these method shell and bash but usually bash is not supported and defualt sh is supported terminal
To sh into the running container, type this:
docker exec -it container_name/container_ID sh
To bash into a running container, type this:
docker exec -it container_name/container_ID bash
and you want to use only bash terminal than you can install the bash terminal in your Dockerfile like RUN apt install bash -y
This is best if you don't want to specify an entry point in your docker build file..
sudo docker run -it --entrypoint /bin/bash <container_name>
If you are using Docker Compose then this will take you inside a Docker container.
docker-compose run container_name /bin/bash
Inside the container it will take you to WORKDIR defined in the Dockerfile. You can change your work directory by
WORKDIR directory_path # E.g /usr/src -> container's path
Another option is to use nsenter.
PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid
It's CentOS 7, already installed vi and vim in my CentOS and I can use them. I run docker in CentOS, when I excute this line below:
docker exec -it mysolr /bin/bash
I cannot use vi/vim in the solr container:
bash: vim: command not found
Why is that and how do I fix it so I can use vi/vim to edit file in docker container?
A typical Docker image contains a minimal set of libraries and utilities to run one specific program. Additionally, Docker container filesystems are not long-lived: it is extremely routine to delete and recreate a container, for instance to use a newer version of a base image.
The upshot of this is that you never want to directly edit files in a Docker container, and most images aren't set up with "rich" editing tools. (BusyBox contains a minimal vi and so most Alpine-based images will too.) If you make some change, it will be lost as soon as you delete the container. (Similarly, you usually can install vim or emacs or whatever, but it will get lost as soon as the container is deleted: installing software in a running container isn't usually a best practice.)
There are two good ways to deal with this, depending on what kind of file it is.
If the file is part of the application, like a source file, edit, debug, and test it outside of Docker space. Once you're convinced it's right (by running unit tests and by running the program locally), docker build a new image with it, and docker run a new container with the new image.
ed config.py
pytest
docker build -t imagename .
docker run -d -p ... --name containername imagename
...
ed config.py
pytest
docker build -t imagename .
docker stop containername
docker run -d -p ... --name containername imagename
If the file is configuration that needs to be injected when the application starts, the docker run -v option is a good way to push it in. You can directly edit the config file on your host, but you'll probably need to restart (or delete and recreate) the container for it to notice.
ed config.txt
docker run \
-v $PWD/config.txt:/etc/whatever/config.txt \
--name containername -p ... \
imagename
...
ed config.txt
docker stop containername
docker rm containername
docker run ... imagename
I'm getting started working with Docker. I'm using the WordPress base image and docker-compose.
I'm trying to ssh into one of the containers to inspect the files/directories that were created during the initial build. I tried to run docker-compose run containername ls -la, but that didn't do anything. Even if it did, I'd rather have a console where I can traverse the directory structure, rather than run a single command. What is the right way to do this with Docker?
docker attach will let you connect to your Docker container, but this isn't really the same thing as ssh. If your container is running a webserver, for example, docker attach will probably connect you to the stdout of the web server process. It won't necessarily give you a shell.
The docker exec command is probably what you are looking for; this will let you run arbitrary commands inside an existing container. For example:
docker exec -it <mycontainer> bash
Of course, whatever command you are running must exist in the container filesystem.
In the above command <mycontainer> is the name or ID of the target container. It doesn't matter whether or not you're using docker compose; just run docker ps and use either the ID (a hexadecimal string displayed in the first column) or the name (displayed in the final column). E.g., given:
$ docker ps
d2d4a89aaee9 larsks/mini-httpd "mini_httpd -d /cont 7 days ago Up 7 days web
I can run:
$ docker exec -it web ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
18: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:3/64 scope link
valid_lft forever preferred_lft forever
I could accomplish the same thing by running:
$ docker exec -it d2d4a89aaee9 ip addr
Similarly, I could start a shell in the container;
$ docker exec -it web sh
/ # echo This is inside the container.
This is inside the container.
/ # exit
$
To bash into a running container, type this:
docker exec -t -i container_name /bin/bash
or
docker exec -ti container_name /bin/bash
or
docker exec -ti container_name sh
Historical note: At the time I wrote this answer, the title of the question was: "How to ssh into a docker container?"
As other answers have demonstrated, it is common to execute and interact with preinstalled commands (including shells) in a locally-accessible running container using docker exec, rather than SSH:
docker exec -it (container) (command)
Note: The below answer is based on Ubuntu (of 2016). Some translation of the installation process will be required for non-Debian containers.
Let's say, for reasons that are your own, you really do want to use SSH. It takes a few steps, but it can be done. Here are the commands that you would run inside the container to set it up...
apt-get update
apt-get install openssh-server
mkdir /var/run/sshd
chmod 0755 /var/run/sshd
/usr/sbin/sshd
useradd --create-home --shell /bin/bash --groups sudo username ## includes 'sudo'
passwd username ## Enter a password
apt-get install x11-apps ## X11 demo applications (optional)
ifconfig | awk '/inet addr/{print substr($2,6)}' ## Display IP address (optional)
Now you can even run graphical applications (if they are installed in the container) using X11 forwarding to the SSH client:
ssh -X username#IPADDRESS
xeyes ## run an X11 demo app in the client
Here are some related resources:
openssh-server doesn't start in Docker container
How to get bash or ssh into a running container in background mode?
Can you run GUI applications in a Linux Docker container?
Other useful approaches for graphical access found with search: Docker X11
If you run SSHD in your Docker containers, you're doing it wrong!
If you're here looking for a Docker Compose-specific answer like I was, it provides an easy way in without having to look up the generated container ID.
docker-compose exec takes the name of the service as per your docker-compose.yml file.
So to get a Bash shell for your 'web' service, you can do:
$ docker-compose exec web bash
If the container has already exited (maybe due to some error), you can do
$ docker run --rm -it --entrypoint /bin/ash image_name
or
$ docker run --rm -it --entrypoint /bin/sh image_name
or
$ docker run --rm -it --entrypoint /bin/bash image_name
to create a new container and get a shell into it. Since you specified --rm, the container would be deleted when you exit the shell.
Notice: this answer promotes a tool I've written.
I've created a containerized SSH server that you can 'stick' to any running container. This way you can create compositions with every container. The only requirement is that the container has Bash.
The following example would start an SSH server attached to a container with name 'my-container'.
docker run -d -p 2222:22 \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CONTAINER=my-container -e AUTH_MECHANISM=noAuth \
jeroenpeeters/docker-ssh
ssh localhost -p 2222
When you connect to this SSH service (with your SSH client of choice) a Bash session will be started in the container with name 'my-container'.
For more pointers and documentation see: https://github.com/jeroenpeeters/docker-ssh
Start a session into a Docker container using this command:
sudo docker exec -i -t (container ID) bash
If you're using Docker on Windows and want to get shell access to a container, use this:
winpty docker exec -it <container_id> sh
Most likely, you already have Git Bash installed. If you don't, make sure to install it.
In some cases your image can be Alpine-based. In this case it will throw:
OCI runtime exec failed: exec failed: container_linux.go:348: starting
container process caused "exec: \"bash\": executable file not found in
$PATH": unknown
Because /bin/bash doesn't exist. Instead of this you should use:
docker exec -it 9f7d99aa6625 ash
or
docker exec -it 9f7d99aa6625 sh
To connect to cmd in a Windows container, use
docker exec -it d8c25fde2769 cmd
Where d8c25fde2769 is the container id.
docker exec -it <container_id or name> bash
OR
docker exec -it <container_id or name> /bin/bash
GOINSIDE SOLUTION
install goinside command line tool with:
sudo npm install -g goinside
and go inside a docker container with a proper terminal size with:
goinside docker_container_name
old answer
We've put this snippet in ~/.profile:
goinside(){
docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside
Not only does this make everyone able to get inside a running container with:
goinside containername
It also solves a long lived problem about fixed Docker container terminal sizes. Which is very annoying if you face it.
Also if you follow the link you'll have command completion for your docker container names too.
To inspect files, run docker run -it <image> /bin/sh to get an interactive terminal. The list of images can be obtained by docker images. In contrary to docker exec this solution works also in case when an image doesn't start (or quits immediately after running).
It is simple!
List out all your Docker images:
sudo docker images
On my system it showed the following output:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
bash latest 922b9cc3ea5e 9 hours ago
14.03 MB
ubuntu latest 7feff7652c69 5 weeks ago 81.15 MB
I have two Docker images on my PC. Let's say I want to run the first one.
sudo docker run -i -t ubuntu:latest /bin/bash
This will give you terminal control of the container. Now you can do all type of shell operations inside the container. Like doing ls will output all folders in the root of the file system.
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Simple
docker exec -it <container_id> bash
in above -it means interactive terminal.
also, with image name:
docker exec -it <REPOSITORY name> bash
I've created a terminal function for easier access to the container's terminal. Maybe it's useful to you guys as well:
So the result is, instead of typing:
docker exec -it [container_id] /bin/bash
you'll write:
dbash [container_id]
Put the following in your ~/.bash_profile (or whatever else that works for you), then open a new terminal window and enjoy the shortcut:
#usage: dbash [container_id]
dbash() {
docker exec -it "$1" /bin/bash
}
2022 Solution
Consider another option
Why do you need it?
There is a bunch of modern docker-images that are based on distroless base images (they don't have /bin/bash either /bin/sh) so it becomes impossible to docker exec -it {container-name} bash into them.
How to shell-in any container
Use opener:
requires to add alias in your environment opener wordpress
works anywhere docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock artemkaxboy/opener wordpress
Instead of wordpress you can use name or id or image-name of any container you want to connect
How it works
Opener is a set of python scripts wrapped-up to a docker image. It finds target container by any unique attribute (name, id, port, image), tries to connect to target using bash. If bash is not found opener tries to connect using sh. Finally if sh is not found either opener installs busybox into target container and connects to the target using busybox shell, opener deletes busybox during disconnection.
$ docker exec -it <Container-Id> /bin/bash
Or depending on the shell, it can be
$ docker exec -it <Container-Id> /bin/sh
You can get the container-Id via docker ps command
-i = interactive
-t = to allocate a psuedo-TTY
you can interact with the terminal in docker container by passing the option -ti
docker run --rm -ti <image-name>
eg: docker run --rm -ti ubuntu
-t stands for terminal
-i stands for interactive
There are at least 2 options depending on the target.
Option 1: Create a new bash process and join into it (easier)
Sample start: docker exec -it <containername> /bin/bash
Quit: type exit
Pro: Does work on all containers (not depending on CMD/Entrypoint)
Contra: Creates a new process with own session and own environment-vars
Option 2: Attach to the already running bash (better)
Sample start: docker attach --detach-keys ctrl-d <containername>
Quit: use keys ctrl and d
Pro: Joins the exact same running bash which is in the container. You have same the session and same environment-vars.
Contra: Only works if CMD/Entrypoint is an interactive bash like CMD ["/bin/bash"] or CMD ["/bin/bash", "--init-file", "myfile.sh"] AND if container has been started with interactive options like docker run -itd <image> (-i=interactive, -t=tty and -d=deamon [opt])
We found option 2 more useful. For example we changed apache2-foreground to a normal background apache2 and started a bash after that.
docker exec will definitely be a solution. An easy way to work with the question you asked is by mounting the directory inside Docker to the local system's directory.
So that you can view the changes in local path instantly.
docker run -v /Users/<path>:/<container path>
Use:
docker attach <container name/id here>
The other way, albeit there is a danger to it, is to use attach, but if you Ctrl + C to exit the session, you will also stop the container. If you just want to see what is happening, use docker logs -f.
:~$ docker attach --help
Usage: docker attach [OPTIONS] CONTAINER
Attach to a running container
Options:
--detach-keys string Override the key sequence for detaching a container
--help Print usage
--no-stdin Do not attach STDIN
--sig-proxy Proxy all received signals to the process (default true)
Use this command:
docker exec -it containerid /bin/bash
To exec into a running container named test, below is the following commands
If the container has bash shell
docker exec -it test /bin/bash
If the container has bourne shell and most of the cases it's present
docker run -it test /bin/sh
If you have Docker installed with Kitematic, you can use the GUI. Open Kitematic from the Docker icon and in the Kitematic window select your container, and then click on the exec icon.
You can see the container log and lots of container information (in settings tab) in this GUI too.
In my case, for some reason(s) I need to check all the network involved information in each container. So the following commands must be valid in a container...
ip
route
netstat
ps
...
I checked through all these answers, none were helpful for me. I’ve searched information in other websites. I won’t add a super link here, since it’s not written in English. So I just put up this post with a summary solution for people who have the same requirements as me.
Say you have one running container named light-test. Follow the steps below.
docker inspect light-test -f {{.NetworkSettings.SandboxKey}}. This command will get reply like /var/run/docker/netns/xxxx.
Then ln -s /var/run/docker/netns/xxxx /var/run/netns/xxxx. The directory may not exist, do mkdir /var/run/netns first.
Now you may execute ip netns exec xxxx ip addr show to explore network world in container.
PS. xxxx is always the same value received from the first command. And of course, any other commands are valid, i.e. ip netns exec xxxx netstat -antp|grep 8080.
There are two options we can connect to the docker terminal directly with these method shell and bash but usually bash is not supported and defualt sh is supported terminal
To sh into the running container, type this:
docker exec -it container_name/container_ID sh
To bash into a running container, type this:
docker exec -it container_name/container_ID bash
and you want to use only bash terminal than you can install the bash terminal in your Dockerfile like RUN apt install bash -y
This is best if you don't want to specify an entry point in your docker build file..
sudo docker run -it --entrypoint /bin/bash <container_name>
If you are using Docker Compose then this will take you inside a Docker container.
docker-compose run container_name /bin/bash
Inside the container it will take you to WORKDIR defined in the Dockerfile. You can change your work directory by
WORKDIR directory_path # E.g /usr/src -> container's path
Another option is to use nsenter.
PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid
Background
I had build a npm server(sinopia) docker image(https://github.com/feuyeux/docker-atue/blob/master/docker-images/feuyeux_sinopia.md), and in the CMD line, it will run the start.sh every time when the container is generated.
CMD ["/opt/sinopia/start.sh"]
This shell will create a yaml file dynamically.
sed -e 's/\#listen\: localhost/listen\: 0.0.0.0/' -e 's/allow_publish\: admin/allow_publish\: all/' /tmp/config.yaml > /opt/sinopia/config.yaml
Question
I wish I could edit this config.yaml when the container is running, because I hope the content should be changed on demand.
see the snapshot photo
As shown above, the first line runs a sinopia container, and in this container, there's /opt/sinopia/config.yaml. But I don't know how to obtain this running container and edit and check this file.
If I did as the line of sinopia-ls, there's a new container runs instead of the before running one.
Thanks guys!
Answer(details please see below what I accepted)
sudo nsenter --target $PID --mount --uts --ipc --net --pid
root#58075317e47d:/# ls /opt/sinopia/
config.yaml config_gen.js start.sh storage
root#58075317e47d:/# cat /opt/sinopia/config.yaml
With docker 1.3, there is a new command docker exec. This allows you to enter a running docker:
docker exec -it <container-id> bash
You named your container, so you can find it using that name.
Then use nsenter (man nsenter) to send the command you want to do.
nsenter --target $$(docker inspect --format {{.State.Pid}} <container_name_or_ID>) --mount --uts --ipc --net --pid <cmd>
More info and solution on how to write inside of a running container : If you run SSHD in your Docker containers, you're doing it wrong!
you just need to mount the folder using -v as an option. i give an example
let's say i have /home/awan/config.yml <--- this file is always dynamic must not put it inside container
i run my container so i can mount that folder into my container
#sudo docker run -i -t -v /home/awan:/home/ubuntu/awan ubuntu/14.04 /bin/bash
after that you just edit config.yml in your /home/awan/config.yml every changes that you applied automaticaly applied inside your docker container (/home/ubuntu/awan/config.yml) because you mount it