Run Code Anywhere: A Modern Guide to Docker


Run Code Anywhere: A Modern Guide to Docker

Imagine a world where your code runs flawlessly across any environment – from your laptop to production servers – without the dreaded "but it works on my machine" syndrome.

That's the promise of containers, and they've revolutionized how we develop, test, and deploy applications.

Containers emerged as a solution to the chaos of maintaining traditional servers, where applications would conflict with each other and overwrite data.

Using Linux namespaces, containers create isolated environments that efficiently allocate resources without interfering with neighboring processes. Which is a fancy way to say you can split CPU and memory without starving other process on the host.

This technology has evolved from virtual machines to the containerization we know today, making development more consistent and deployment more reliable, but most importantly, more resource efficient.

What's the Problem?

Back in the day (10-20 years ago), companies used to hold in-house massive servers in their basements.

These servers ran multiple applications that frequently conlicting with each other – requiring different versions of utilities, fighting over disk space and memory, and as a result sometimes overwriting each other's data.

It was a maintenance nightmare (although at the time, it was just "IT life").

Virtual Machines Changed Everything

The tech world's first attempt at solving this was virtual machines – completely isolated environments with their own operating systems.

While this worked, it was resource-intensive and inefficient.
Don't get me wrong, this technology was born in the seventies, and was the go-to approach for about three decades, but we're here to talk about modern days.

Virtual machines essentially duplicate entire operating systems, consuming significant resources.

The Container Approach: Lightweight Isolation

Containers emerged based on Linux namespaces, creating efficient isolation without the overhead.

They allow different applications to run side-by-side without conflict, sharing the same underlying system while maintaining separation.

This means you can:

  1. Run multiple applications without conflicts
  2. Ensure consistent environments from development to production
  3. Use minimal resources compared to virtual machines
  4. Package applications with all their dependencies

“With Docker, you can spin up a new container in seconds, which is significantly faster than provisioning a full virtual machine, leading to faster development cycles and improved agility.”

- The Docker documentation

Essential Container Commands

Basic Commands:

  • podman/docker ps - List running containers
  • podman/docker ps -a - List all containers (including stopped ones)
  • podman/docker images - View stored container images
  • podman/docker pull [image] - Download container images
  • podman/docker run [image] - Start a container
  • podman/docker run -it [image] sh - Start a container with interactive shell
  • podman/docker run -d [image] - Run container in detached mode
  • podman/docker run -p [host:container] - Map ports between host and container
  • podman/docker run -P - Map random ports
  • podman/docker stop [container] - Stop a running container
  • podman/docker container prune - Remove all stopped containers

Build and Management:

  • podman/docker build -t [name] . - Build a container from Dockerfile
  • podman/docker tag [id] [name] - Add a name to an existing image
  • podman/docker exec -it [container] sh - Get a shell in a running container

Compose Commands:

  • podman/docker compose up - Start multi-container environment
  • podman/docker compose down - Stop and remove multi-container environment
  • podman/docker compose logs - View logs from compose environment
  • podman/docker compose stop [service] - Stop specific service in compose
  • podman/docker compose start [service] - Start specific service in compose

Building Efficient Containers

Building containers is rather easy, and while there are tools to help with that, here's a simple Golang image:

FROM golang:alpine
WORKDIR /app
COPY . .
RUN go build
EXPOSE 8080
CMD ["./main"]

Run `docker build -f my-container.Dockerfile .` (can skip the -f

A pro tip is the multi-stage build approach.

This dramatically reduces container size by using one container to build the application and another minimal container to run it (basically implementing a CI pipeline into your container build process):

FROM golang:alpine AS builder
WORKDIR /app
COPY . .
RUN go build

FROM scratch
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

What we did here is to build the app as usual, then take only the binary artifact into a distro-less image!

This approach reduced the container size from 340MB to just 7MB!!!


Development Workflow Enhancement

For development, mounting your local directory to the container creates a powerful workflow:

services:
app:
image: myapp
volumes:
- ./:/app
command: tail -f /dev/null

This setup lets you make code changes on your local machine and see them instantly reflected in the container, streamlining the development-test cycle.

All that's left is to `docker exec -it

Containers have transformed development workflows from frustrating environment mismatches to seamless, consistent experiences.

Whether you're a solo developer or part of a large team, mastering containers is now an essential skill that will make your code run smoothly anywhere, and makes team work, open source, or just life-long projects because infinitely easier to maintain and work on!


Thank you for reading.
Feel free to reply directly with any question or feedback.
Have a great weekend!

ESPRESSO FRIDAYS

Every once in a while I send hand picked things I've learned. Kind of like your filter to the tech internet. No spam, I promise!

Read more from ESPRESSO FRIDAYS

SQLite Is the ULTIMATE Choice For 99% of Projects When you need to crack a nut, you grab a nutcracker, not a sledgehammer. So why, when it comes to databases, do so many of us immediately reach for a heavy, complex solution, just because we “feel” it’s right? too much? This simple question changes how you look at building software.The default solution for most developers is to spin up a dedicated database server like MySQL, Postgres, or a NoSQL option. This means dealing with separate running...

I've Been Using AWS Wrong for YEARS... For years, my approach to AWS felt like a battle. As a DevOps engineer and later and architect, building infra always involved a tedious process of carefully building templates and structure, reviewing, deploying, testing and iterating over and over. I’d either spend hours clicking through the console or writing endless infrastructure code, always feeling like I was one misconfiguration away from a headache. It turns out, I was making it much harder than...

You've been lied to about self hosting... This issue is brought to you by: Auth0, my auth provider for the last 6 years. Join their free virtual dev_day on June 18th to learn how to secure AI agents and applications. Save your free spot That title might sound a bit aggressive, but this isn't about hating on hosting platforms. It's about loving the freedom, control, and cost-savings that come from owning your deployment process, without giving up the slick, easy experience we all love. And...