Pular para o conteúdo
← Back to Skalablog

Published article

5 Docker Compose Tutorial Steps: Run to MCP

AnthropicNext.jsCursor

A five-megabyte Go binary should not need a whole guest operating system behind it. Docker makes each service a process that fakes being an OS, so a payment gateway, a database and a queue all start with one command. This docker compose tutorial rebuilds that demo step by step and adds MCP on top.

What Docker actually is, and how it differs from a virtual machine

Docker is a container runtime: it runs each application as an isolated process that shares the host operating system's kernel instead of booting a full guest OS. A container is, in the words of the Full Cycle session this article is based on, just a process that has been tricked into thinking it is a complete operating system. When it needs disk, network or other I/O, the Docker layer translates those calls to the host kernel.

A virtual machine works differently. Each VM boots its own operating system, which consumes gigabytes of disk and substantial memory before your application does anything. A Go binary of a few megabytes does not need an entire OS behind it, and starting a VM takes minutes while starting a container takes seconds. Docker development began in 2013 and became the de facto standard container tooling during the following years; alternatives exist, including runtimes aimed at Kubernetes clusters.

The practical comparison looks like this:

DimensionVirtual machineDocker container
Operating systemFull guest OS per VMShares the host kernel
Startup timeMinutes (boot)Seconds (process start)
Resource overheadHigh, OS includedLow, process only
LifecycleLong-lived machineKill it and state is gone

That last row is a feature, not a flaw, in development. Services start with one command and are wiped with another, which is why developers who adopted containers stop reformatting machines to clear out accumulated software.

Images and containers: the first commands worth memorizing

An image is a read-only template, and a container is a running instance of that image, much like a class and its instances in object-oriented programming. Images live in registries; Docker Hub is the default one. When you run an image that is not cached locally, Docker downloads it first.

Three commands cover the fundamentals demonstrated in the session:

  1. docker run hello-world creates a new container from the hello-world image. The container prints a message and exits, because its process finished.
  2. docker ps lists containers that are currently running. The hello-world container does not appear, because it already exited; docker ps -a lists every container, including stopped ones.
  3. docker exec -it <container> bash opens an interactive shell inside a running container. This is different from docker run, which always creates a new container.

One detail trips up beginners: container names are random strings unless you specify one, and an exited container still exists on disk until you remove it with docker rm. Containers are also ephemeral by design. Editing a file inside a running container changes nothing in the image, so deleting the container deletes your edit. That behavior is intentional, and the next section shows the supported way around it.

Ports, docker exec and bind mounts: developing inside a container

Running the Nginx web server image with docker run nginx starts a live server that exports port 80, but curl localhost from your machine fails. The container is a separate network namespace: its localhost is not your localhost. You can confirm the server works by running docker exec -it <id> bash and curling from inside, where the default index page responds.

To reach the server from your machine, publish a port: docker run -p 8080:80 nginx maps host port 8080 to container port 80. Now curl localhost:8080 and your browser both hit the Nginx container. This mapping, not the container's internal port declaration, is what makes a service reachable.

To edit files without losing them when the container dies, use a bind mount. A bind mount maps a folder on your machine to a folder inside the container, so writes on either side appear on both. The session used this pattern:

bash docker run -p 8080:80 -v "$(pwd)/html":/usr/share/nginx/html nginx

With that mount in place, an index.html created on the host is served immediately, and killing the container costs nothing because the files live on the host. Note the terminology: -v with a host path is a bind mount, not a named volume, even though the flag says volume. Named volumes are the right tool for data you want Docker to manage, such as a database's storage directory.

The Dockerfile is the other half of the picture. It describes how to build an image: a FROM base such as golang:1.24-alpine, a WORKDIR, a COPY of project files, and a CMD. In the demo, the command tail -f /dev/null kept the container alive as a placeholder so the developer could exec in and run go run main.go manually during development.

Docker Compose tutorial: a Go API, Postgres and Redis in one file

Docker Compose manages multiple containers from a single YAML file, which is the point where a demo becomes a usable development environment. The session's file defined three services: an app built from the local Dockerfile with port 8080 published and the project folder bind-mounted to /app, a postgres service using the PostgreSQL 16 image with environment variables for user, password and database plus a named volume, and a redis service added with a few lines. One command, docker compose up -d, brings the whole stack up; docker compose down removes it.

The most common beginner failure appeared on camera, and it is worth repeating. The generated Go code connected to Postgres at localhost, and the query failed. Inside a Compose network, services reach each other by service name, not localhost: the connection host must be postgres, the name of the service in the file. Containers on the same Compose project share a network automatically.

Two more lessons from the run:

  • Database schema files can be applied with docker compose exec postgres psql ... -f /init.sql, or wired into the Postgres image's init directory so they run on first startup. Either way, keep SQL scripts next to the Compose file so teammates get the same schema.
  • Compose is a development and small-deployment tool. For production container management, the presenter pointed to Kubernetes, ECS or Google Cloud Run; Compose can run in production with restart policies, but it is not the common choice at scale.

The payoff is reproducibility. Commit the Dockerfile, the Compose file and the SQL to a repository, and a colleague reproduces the entire environment with one command, on Linux, macOS or Windows.

Docker Desktop, Docker Engine and WSL2: which setup to install

Two products share the Docker name, and the distinction matters. The Docker Engine Community Edition is open source and free, with the core commands and nothing else. Docker Desktop is Docker Inc.'s commercial application that bundles the engine with a graphical interface, container and log inspection, and security scanning through Docker Scout; it is free for personal use and small companies, with paid tiers for larger organizations.

On Windows, the session's recommendation was unambiguous: use WSL2, the Windows Subsystem for Linux, regardless of whether you add Docker Desktop. Docker was built for Linux, and WSL2 gives it a real Linux environment instead of a PowerShell workaround. On macOS, Docker Desktop is the straightforward path. Teams on modest hardware sometimes run the Community Edition directly inside WSL2 without Desktop to save memory, which works fine at the cost of the graphical tooling.

MCP: managing Docker containers from your AI editor

The Model Context Protocol (MCP) is Anthropic open standard, introduced in November 2024, for connecting AI assistants to external tools and data sources. An MCP server exposes three primitives: tools, which let the model perform actions; resources, which let it read data such as logs or documents; and prompts, reusable instruction templates. OpenAI announced support for the protocol in March 2025, and Google's Gemini followed with its own adoption announcement later that year, which is why MCP servers now appear in most AI editors. Anthropic announcement is at model-context-protocol.

The demonstration used the official Docker MCP server registered in Cursor, an AI-first code editor built on VS Code. Once enabled, the assistant could list running containers, remove the Redis container with the force flag, and fetch Postgres container logs, each action surfaced as an explicit tool call the user approves before it runs.

The broader point from the session: AI coding fails most often from missing context, not missing capability. In the live demo, vague prompts made the assistant edit the wrong files and invent Compose changes; a precise prompt that named the exact command produced the right result immediately. MCP addresses this structurally, giving the model a governed way to query your real application state, documentation and infrastructure instead of guessing. Teams can also write custom MCP servers that expose their own business rules and internal APIs.

FAQ

  • Do I need Docker Desktop to use Docker Compose?

No. Compose ships with the open-source Docker Engine, so a Linux machine or WSL2 setup runs it without Desktop. Docker Desktop adds a GUI, log inspection and Docker Scout on top of the same engine.

  • Why does my app get 'connection refused' to Postgres in Docker Compose?

Almost always because the connection host is localhost. Inside a Compose network, your app must connect to the service name, for example postgres, because containers resolve each other by service name on the shared network.

  • Is a Docker container a lightweight virtual machine?

No. A container is a process on the host that uses the host kernel, with an isolated filesystem and network view. A VM boots a full guest operating system, which is why containers start in seconds and VMs take minutes.

  • Can I keep data when I remove a Postgres container?

Yes, if the database directory is stored in a named volume declared in your Compose file. Bind mounts to a host folder work too; without either, deleting the container deletes its data.

From a warm-up live to your own written knowledge

This session was a warm-up for Full Cycle's April 2025 immersion, where a Go payment gateway, a Next.js anti-fraud service, Kafka and a Next.js frontend all run on the Docker base shown here. The lesson generalizes: deep technical knowledge usually lives in long videos and live sessions, where it is hard to search, quote or revisit.

If you produce that kind of content, Skala Blog turns a YouTube video into a structured, publishable article: paste the URL, get a transcription, and edit the generated draft. The same Docker walkthrough that takes 100 minutes to watch becomes a reference readers can scan in five.

Source video