DEV Community

Konrad Kądzielawa
Konrad Kądzielawa

Posted on

NetBox in Docker: The Migration Problems That Mattered More Than the Install

Installing NetBox is not the hard part.

The hard part starts when NetBox is no longer an empty application.

When it already contains valuable infrastructure data, every change becomes more sensitive. A broken test instance is annoying. A broken source of truth is a real operational problem.

This article is not a clean "how to install NetBox in Docker" guide.

It is a short case study about the problems that mattered during a real migration-like process: building a safer Docker-based NetBox environment, restoring data, separating application health from automation errors, and avoiding destructive troubleshooting habits.

All names and paths in this article are anonymized. The examples use generic names such as /opt/netbox-ops.


The goal

The goal was not simply:

Run NetBox in Docker.
Enter fullscreen mode Exit fullscreen mode

The real goal was:

Create a safer, reproducible NetBox environment that can be tested,
restored, automated and later used as the base for more advanced workflows.
Enter fullscreen mode Exit fullscreen mode

That difference matters.

A Dockerized NetBox setup is useful not only because it is easier to start. It is useful because it creates a boundary:

configuration
data
media
scripts
logs
runtime
Enter fullscreen mode Exit fullscreen mode

Each part becomes easier to reason about.


Why I did not start directly on production

The most important decision was to avoid learning directly on the main environment.

Instead of changing the existing NetBox instance, I created a separate proof-of-concept environment.

The pattern was:

production-like data
separate Docker directory
separate Compose stack
controlled restore
manual verification
only then further automation
Enter fullscreen mode Exit fullscreen mode

A simplified layout looked like this:

/opt/netbox-ops
├── compose
├── backups
├── imports
├── media
└── scripts
Enter fullscreen mode Exit fullscreen mode

The exact path is not important.

The important part is that the environment had a clear operational boundary.

This made it possible to test migration steps, imports and scripts without treating the main NetBox instance as a playground.

The lesson was simple:

If the application already contains valuable infrastructure data,
do not test migration logic directly on the only working copy.
Enter fullscreen mode Exit fullscreen mode

Problem 1: A running container is not the same as a healthy application

One of the first practical checks was container state.

Commands like these are obvious:

docker compose ps
docker ps -a
docker compose logs --tail=100
Enter fullscreen mode Exit fullscreen mode

But the important part was not running the commands.

The important part was not trusting only one signal.

A container can be running while the application is not usable.

A container can also restart quickly enough that the first look does not show the real failure.

So I used a few separate checks:

docker compose ps
docker compose logs netbox --tail=100
docker compose logs postgres --tail=100
docker compose logs redis --tail=100
curl -I http://127.0.0.1:8000/login/
Enter fullscreen mode Exit fullscreen mode

That helped separate several questions:

Is Docker running?
Is the NetBox container running?
Is NetBox actually responding?
Is the database reachable?
Is Redis healthy?
Is the problem inside the app or outside it?
Enter fullscreen mode Exit fullscreen mode

This sounds basic, but it prevents a lot of bad troubleshooting.


Problem 2: Exited 137 looked like a NetBox issue, but it was not necessarily one

At one point, a container exited with code 137.

That is one of those errors that can be misleading if you read it only as:

NetBox failed.
Enter fullscreen mode Exit fullscreen mode

A better first interpretation is:

The process was killed.
Enter fullscreen mode Exit fullscreen mode

Often this points toward memory pressure, OOM killer activity, or a host-level resource problem.

The diagnostic path was:

docker ps -a
docker logs <container_name> --tail=200
dmesg -T | grep -i -E "killed|oom|out of memory"
free -h
df -h
docker system df
Enter fullscreen mode Exit fullscreen mode

The lesson:

Exited 137 is not automatically an application bug.
Check the host before rewriting the application configuration.
Enter fullscreen mode Exit fullscreen mode

This is especially important with NetBox because migrations, imports or plugin-related tasks may temporarily use more resources than a quiet application instance.

If the host is under pressure, restarting containers without checking the reason only hides the real problem.


Problem 3: Script errors can look scarier than they are

Another issue appeared during custom automation.

A script returned a database-related error similar to:

duplicate key value violates unique constraint
Enter fullscreen mode Exit fullscreen mode

At first glance, that looks serious.

But the important question was:

Did NetBox fail, or did only the automation script fail?
Enter fullscreen mode Exit fullscreen mode

Those are different problems.

The application health check was:

docker compose ps
docker compose logs netbox --tail=100
curl -I http://127.0.0.1:8000/login/
Enter fullscreen mode Exit fullscreen mode

If NetBox still responds and the containers are healthy, the problem may be limited to the custom script.

In this case, the real issue was idempotency.

The script tried to create objects that already existed.

The fix was not "repair NetBox".

The fix was to make automation safer:

check if object exists first
create only when missing
update when needed
skip when unchanged
write a skipped/changed summary
Enter fullscreen mode Exit fullscreen mode

This changed the way I treated all import and cleanup scripts.

A good NetBox script should not assume an empty database.

It should expect that some objects already exist.


Problem 4: Do not confuse cleanup with destruction

During Docker troubleshooting, there is always a temptation to run aggressive cleanup commands.

Examples:

docker system prune -a
docker volume prune
docker compose down -v
rm -rf /var/lib/docker
Enter fullscreen mode Exit fullscreen mode

These commands have their place.

But they should not be a reflex.

For NetBox, deleting volumes can mean deleting the database or uploaded media if the environment is not designed carefully.

That is why I prefer this rule:

Before deleting anything, identify where the database, media and backups live.
Enter fullscreen mode Exit fullscreen mode

The safer pattern is:

docker compose ps
docker volume ls
docker volume inspect <volume_name>
docker inspect <container_name>
Enter fullscreen mode Exit fullscreen mode

Then decide.

For a source-of-truth system, "clean everything and try again" is often the wrong mindset.

The better mindset is:

observe
identify
back up
change one thing
verify
Enter fullscreen mode Exit fullscreen mode

Problem 5: Media restore is easy to forget

When moving a NetBox environment, the database is the obvious part.

Media files are easier to miss.

The database may restore correctly, but attachments, uploaded files or generated assets may not appear if media is not restored or mounted correctly.

That creates a strange situation:

NetBox works,
objects exist,
but files or images are missing.
Enter fullscreen mode Exit fullscreen mode

The fix is not complicated, but the lesson is important:

A NetBox restore is not complete until database and media are both verified.
Enter fullscreen mode Exit fullscreen mode

My basic checklist became:

database restored
superuser/admin access verified
objects visible
media path mounted
attachments/images visible
logs clean enough
Enter fullscreen mode Exit fullscreen mode

Problem 6: Restart policies must be verified, not assumed

The environment also needed to survive a VM reboot.

This part is small, but operationally important.

Docker services should start with the host:

sudo systemctl enable docker.service
sudo systemctl enable containerd.service
Enter fullscreen mode Exit fullscreen mode

Containers should have an intentional restart policy:

restart: unless-stopped
Enter fullscreen mode Exit fullscreen mode

But I do not like assuming that Compose settings are actually applied.

I prefer checking:

docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' <container_name>
Enter fullscreen mode Exit fullscreen mode

Expected result:

unless-stopped
Enter fullscreen mode Exit fullscreen mode

Then test the real scenario:

sudo reboot
Enter fullscreen mode Exit fullscreen mode

After the host comes back:

docker compose ps
curl -I http://127.0.0.1:8000/login/
Enter fullscreen mode Exit fullscreen mode

This is simple, but it removes guessing.


What I avoided documenting on purpose

I did not want this process to turn into another generic NetBox installation tutorial.

So the focus was not:

install package X
copy file Y
run command Z
Enter fullscreen mode Exit fullscreen mode

The more valuable part was the operational behavior:

What happens when a container is killed?
What happens when a script partially fails?
What happens when old data already exists?
What happens when media is missing?
What should not be deleted during troubleshooting?
Enter fullscreen mode Exit fullscreen mode

These are the problems that appear after the installation guide ends.


What I learned

The biggest lesson was:

Docker does not automatically make NetBox safe.
But it gives you tools to build a safer operating model.
Enter fullscreen mode Exit fullscreen mode

The useful parts were:

a separate POC environment
clear project directories
persistent data and media
controlled restore
container-level health checks
application-level health checks
idempotent scripts
careful cleanup rules
verified restart policies
Enter fullscreen mode Exit fullscreen mode

The most important troubleshooting rule was:

Always separate application failure from automation failure.
Enter fullscreen mode Exit fullscreen mode

A failed import script does not always mean NetBox is broken.

A stopped container does not always mean NetBox configuration is wrong.

A restored database does not always mean the restore is complete.

Those distinctions matter.


What comes next

The Docker environment was only the foundation.

The harder problem came after that:

How to import real infrastructure data into NetBox without creating chaos?
Enter fullscreen mode Exit fullscreen mode

That means dealing with DNS exports, IP addresses, hostnames, devices, interfaces, duplicates, naming problems and incomplete information.

That is the topic of the next part.

Top comments (0)