A Beginner's Guide to Essential Commands to Fix Container Setup Issues
The five essential commands that all developers should know in order to develop and build applications in Docker. This will pinpoint the exact reasons for failure.
Join the DZone community and get the full member experience.
Join For FreeYou followed the tutorial. You ran Docker Run. And... nothing. The container exited immediately. Or maybe it is running, but localhost just shows “This site can’t be reached.” We’ve all been there. When you’re new to Docker, a failing container can feel like a sealed black box. You know something is wrong inside, but you have no idea how to look.
In this quick guide, I’ll show you the five essential commands to open that box, see what’s happening, and fix your broken containers.
The "Broken Application" and How to Fix It
In order to help developers debug their setups, let us start with a small application in Python with some errors and see how we can debug this further. Here are the following files.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello from docker!'
if __name__ == '__main__':
# To make sure the container is listening to all network addresses.
app.run(host='0.0.0.0', port=3000)
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 3000
Build it to check for failure:
# Build the broken-image with tag my-broken-app
$ docker build -t my-broken-app.
# Run the container
$ docker run -p 3000:3000 my-broken-app
There will be nothing to see, and it will be returned directly to the command prompt. Unfortunately, the container didn't start. Let's start debugging this to check for errors.
1. docker ps -a: Check for Running Docker Processes
The first thing to try out is to run: docker ps to check for containers.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# ... it's empty!
This is the first trap that beginners run into. docker ps only shows currently running containers. Since our app has failed and stopped, this will not be there in the list.
The command to run is docker ps -a (In short this will be show running/stopped containers).
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c6b8e0f6a2d1 my-broken-app "python App.py" 8 seconds ago Exited (1) 8 seconds ago upbeat_rogers
This reveals certain information that we can use to debug it further. We can check for our my-broken-app container. Looking at the STATUS column: Exited (1) 8 seconds ago. This means the container did run, however, the main process inside it (our python App.py command) failed and exited with a non-zero status code (This signals there was an error)
When do we use this: Use docker ps -a immediately when a container appears not to start. It will confirm if it failed, or (in another common case) if it's running but there is a PORT forwarding issue in your run command (the PORTS column would be blank).
2. docker logs [container_id]: The "What Went Wrong" Command
Okay, we know the container failed. Now we need to know why.
Every container has its own log stream, which captures the standard output (stdout) and standard error (stderr) of its main process. docker logs lets you read it.
Grab the CONTAINER ID (or NAMES) from the docker ps -a command and use it here:
# You can use the ID 'c6b8e0f6a2d1' or the name 'upbeat_rogers'
$ docker logs c6b8e0f6a2d1
Output:
python: can't open file '/app/App.py': [Errno 2] No such file or directory
And here we see the problem. The error isn't some complex issue; it's a simple and frankly quite familiar "File not found" error. Our CMD has a bug.
When we use this: Use docker logs, when the container has an EXITED status. Use this to understand why and how it failed.
3. docker exec -it [container_id] /bin/sh: A Peek Inside the Container
Let's fix our Dockerfile (change App.py to app.py) and rebuild: docker build -t my-fixed-app .
What if we encounter a different problem? What if the container is working but the app is not working (e.g., localhost:3000 shows "500 Internal Server Error").
# Run the fixed app, but in the background
$ docker run -d -p 3000:3000 my-fixed-app
# Check what is running
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3f9a0c3b7e8 my-fixed-app "python app.py" 5 seconds ago Up 1 second 0.0.0.0:3000->3000/tcp eager_jones
It's Up, but it's not working. How can we "get inside" it to poke around?
Use docker exec. This command lets you run a new process inside an already running container. In this case we will use it to run a simple shell command.
exec: Execute a new command.-it: It stands for "interactive terminal." This will attach your keyboard and screen to your running container.[container_id]: The ID of the running container (e.g.,a3f9a0c3b7e8)./bin/sh: This is the command that we want to run (a simple Shell command). (/bin/bash and /bin/sh are commonly used).
$ docker exec -it a3f9a0c3b7e8 /bin/sh
/app #
Here you are looking inside the container! That # shows that it is inside the containers' file system:
/app #ls -l: List the files along with the related permissions./app #cat app.py: Show the local file to check if the contents are okay./app #env: To check for the environment variables./app #ps aux: Check if the Python process is working.
Use this whenever the container is up and running; however, the app is not. This is very powerful and will help quite a lot in debugging real-world issues.
4. docker run -it --entrypoint /bin/sh [image_id]: The "Override" Command
This is a very neat trick. What if your container fails so fast (like our first my-broken-app example) that you can't exec into it, and the logs are so bad that you can't use it to debug.
In reality, Docker has a helpful command to override the CMD or ENTRYPOINT in the Dockerfile.
$ docker run -it --entrypoint /bin/sh my-broken-app
/app #
Let's break this down:
run -it: Start a new container in interactive mode.--entrypoint /bin/sh: This is the command. It tells Docker to ignore theCMDin theDockerfile(thepython App.pypart). Instead, this will just run the shell.my-broken-app: The image we want to inspect.
It drops you into a shell inside a brand new container built from your broken image. It enables you to interact with the filesystem precisely as it was when the CMD was about to run. Now you can run ls -l and see “A-ha! The file is app.py, but my CMD was calling App.py.” You found the bug by exploring the image itself.
When to use this: Use this “override” command when a container won’t start, and Docker logs are not clear. It is your master key to get into any image.
5. docker system prune: The Cleanup Command to Delete Zombie Stuff
With all the broken apps that are running, there will be a lot of dangling images from the older failed builds. Some of the images can be huge and eat into gigabytes of disk space.
Recap:
docker ps -aShows all containers.docker image lsshows all your images, including ones that are tagged<none>(These are the dangling images).
You can remove the container one by one by doing docker rm [id] for containers, docker rmi [id] for images). However, there is a much easier way.
$ docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all build cache
Are you sure you want to continue? [y/N] y
It will safely clean all the dangling stuff from your local setup.
When do we run this: Run docker system prune after a developmental session to reclaim disk space and keep the environment clean.
The Complete Debugging Workflow
Here is the recap for the entire workflow:
- For container fails: Run
docker ps -ato find the container and see the "EXITED" status column to pinpoint what is wrong. - Check for the error logs: Run
docker logs [container_id]to find and know about the error logs of the container - Exploration stuff if the app isn't working:
- In case the container didn't start, run
docker run -it --entrypoint /bin/sh [image_id], to explore the local file system. - If the container is running but buggy, with the app not running properly, run
docker exec -it [container_id] /bin/sh{bash}to order to debug it.
- In case the container didn't start, run
- Fix and rebuild: Fix the code and Dockerfile and build the container again.
- Cleaning up: Run
docker system pruneto clear out all the dangling stuff.
Opinions expressed by DZone contributors are their own.
Comments