At this point, we are pretty familiar with getting containers running in Docker and how to monitor them from the cli or Docker desktop. Now we want to look at how to connect to a docker container while it is running. Connecting to a docker container is similar to how you would SSH into a remote machine to perform administrative tasks. With Docker, you don’t actually need SSH, as there are commands built into Docker that allow you to connect to a shell of running containers easily. Let’s see some ways to connect to a running Docker container now.
Docker Container Run -it
We’ve already seen the docker container run command in the prior Docker tutorials. It starts a container for us. During this process, we can connect to the container at the terminal right from startup. This leads us to a quick discussion of Docker Options. You might also see options referred to as a Flag. Here are the ones we are interested in for this exercise.
- -i or –interactive Keep STDIN open even if not attached
- -t or –tty Allocate a pseudo-TTY
With this knowledge in mind, the first way to connect to a Docker container is by running a new container in interactive mode. We are using -i and -t at the same time by simply typing -it. At the end of the command, we are instructing Nginx to start up a bash shell with /bin/bash
$ docker container run -it --name webserver nginx /bin/bash
This launches the webserver container, and then we are provided a bash prompt inside the container as indicated by the root@6b2693e38c19:/# prompt. This means we are the root user and the characters after the @ sign are the id of the container we are in. Once inside, we do a quick ls -al
to see the contents of the container.
root@6b2693e38c19:/# ls -al total 80 drwxr-xr-x 1 root root 4096 Oct 2 18:55 . drwxr-xr-x 1 root root 4096 Oct 2 18:55 .. -rwxr-xr-x 1 root root 0 Oct 2 18:55 .dockerenv drwxr-xr-x 2 root root 4096 Sep 8 07:00 bin drwxr-xr-x 2 root root 4096 Jul 10 21:04 boot drwxr-xr-x 5 root root 360 Oct 2 18:55 dev drwxr-xr-x 1 root root 4096 Sep 10 12:33 docker-entrypoint.d -rwxrwxr-x 1 root root 1202 Sep 10 12:32 docker-entrypoint.sh drwxr-xr-x 1 root root 4096 Oct 2 18:55 etc drwxr-xr-x 2 root root 4096 Jul 10 21:04 home drwxr-xr-x 1 root root 4096 Sep 10 12:33 lib drwxr-xr-x 2 root root 4096 Sep 8 07:00 lib64 drwxr-xr-x 2 root root 4096 Sep 8 07:00 media drwxr-xr-x 2 root root 4096 Sep 8 07:00 mnt drwxr-xr-x 2 root root 4096 Sep 8 07:00 opt dr-xr-xr-x 159 root root 0 Oct 2 18:55 proc drwx------ 2 root root 4096 Sep 8 07:00 root drwxr-xr-x 3 root root 4096 Sep 8 07:00 run drwxr-xr-x 2 root root 4096 Sep 8 07:00 sbin drwxr-xr-x 2 root root 4096 Sep 8 07:00 srv dr-xr-xr-x 11 root root 0 Oct 2 18:26 sys drwxrwxrwt 1 root root 4096 Sep 10 12:33 tmp drwxr-xr-x 1 root root 4096 Sep 8 07:00 usr drwxr-xr-x 1 root root 4096 Sep 8 07:00 var root@6b2693e38c19:/#
This shows us all the files inside the container that is based on the Nginx image. Once in the container, you can change config files, download files from the internet, or any other common administrative task that you might do from the shell of a running server. To leave the shell in the container, just type exit
. Note that since all we did with this container was to run bash, once you exit the bash shell the container will stop running. This is because when you start an Nginx container and override the default command of running the Nginx process, there is nothing left to keep the container running once the shell is exited. In other words, containers only run as long as the command that it ran on startup runs.
Docker Container Exec -it
The approach that probably makes more sense is to connect to a container that is already running and doing its normal job. So let’s start a new Nginx webserver once again, but simply let the normal processes start. We will not add any commands to the end of the docker command.
$ docker container run --name webserver nginx
Now that the container is running, we can connect to it using the docker exec command.
$ docker container exec -it webserver bash
Once again we are connected to the container at a bash prompt. We do a pwd command and can see that we are at the root of the filesystem.
root@e9108992aa35:/# pwd /
We can even view the default index.html file that is served if you were to browse to the container.
root@e9108992aa35:/# cat /usr/share/nginx/html/index.html <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
This approach is likely the most useful and common.
Running One Off Commands
The section above made use of the -it flags. That makes it interactive and gives us a terminal to work in. By omitting the -it options, we can run commands from the Docker cli that get proxied into the container, ran, and then the results are printed back to the host terminal. To see how this works, we can redo the examples from above while leaving off the -it options.
> docker container exec webserver ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var >
We’ve been using the name of the container to determine which container we connect to. If you did not name your container, then you simply use the id of the container with the command instead.
> docker container exec e9108992aa35 ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
In this next example, we can use docker exec in a one-off style to view the nginx.conf file in the container.
> docker container exec webserver cat /etc/nginx/nginx.conf user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
Learn More
- Common Tasks Ssh Into A Container (phase2.github.io)
- How To Connect To Docker Container (linuxize.com)
- Docker Container Communication (linode.com)
- Cloud Instances Connecting Connecting To Docker (docs.joyent.com)
- How To Connect To A Running Docker Container (garrymarsland.com)
- Docker Container Shell (baeldung.com)
- Docker Connect Containers Together (middlewareinventory.com)
- How Do I Get Into A Docker Containers Shell (stackoverflow.com)
Summary
The main takeaway is that if you want to connect to a container, you’ll want to be using the -it options with either docker container run or docker container exec. When used with the run command, you’re starting a new container interactively. The more common and useful approach however is to use this flag with the docker container exec command.