{"componentChunkName":"component---src-gatsby-theme-chronoblog-templates-note-js","path":"/notes/docker-compose-overview/","result":{"data":{"mdx":{"parent":{"__typename":"File","fields":{"gitLogLatestDate":"2026-06-20 00:59:47 +0200"}},"id":"16a6b8f0-569b-599f-8b57-8fa27ad43c1b","excerpt":"Docker Compose runs multi-container applications from a single YAML file. One command can start an API, a database, a message broker, and…","frontmatter":{"title":"Docker Compose overview","date":"2026-06-20 00:01:00 UTC","job_ad":null,"job_ad_id":null,"job_ad_url":null,"tags":["docker-compose","docker","devops"],"cover":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAvklEQVQoz62SbWvDMAyE8/9/5ta4HzY3sWzHkvPyjC4dZCXtMujBgRGHpNO54cVolmVhyyvua/9h81TAz4CVWzxs+JeFdeuV9052Lb+/BfxnRUTw3tP3Hd3FaE+RizdMjZSUnAwtRikDoVfOLnF2mZRG+k5xbSbnmSaESk4ztVZUFTOjDBMhjAx5IsVKe8o4VxBRvP8gRiXKhMiI2fytl3B9H7DMsn/DwynvB3O7IQdSfh7G4zS3ml8bvvpjfwG6thbGwptEigAAAABJRU5ErkJggg==","aspectRatio":2.0869565217391304,"src":"/static/9f115bf35a6da1b6448207f4d5903c84/c4ecb/cover.png","srcSet":"/static/9f115bf35a6da1b6448207f4d5903c84/57ab0/cover.png 192w,\n/static/9f115bf35a6da1b6448207f4d5903c84/f4739/cover.png 384w,\n/static/9f115bf35a6da1b6448207f4d5903c84/c4ecb/cover.png 768w","srcWebp":"/static/9f115bf35a6da1b6448207f4d5903c84/dd090/cover.webp","srcSetWebp":"/static/9f115bf35a6da1b6448207f4d5903c84/ae504/cover.webp 192w,\n/static/9f115bf35a6da1b6448207f4d5903c84/fef30/cover.webp 384w,\n/static/9f115bf35a6da1b6448207f4d5903c84/dd090/cover.webp 768w","sizes":"(max-width: 768px) 100vw, 768px","presentationWidth":768,"presentationHeight":366},"resize":{"src":"/static/9f115bf35a6da1b6448207f4d5903c84/c4ecb/cover.png"}}}},"fields":{"slug":"/notes/docker-compose-overview/","readingTime":{"text":"4 min read"}},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Docker Compose overview\",\n  \"date\": \"2026-06-20 00:01:00 UTC\",\n  \"cover\": \"./cover.png\",\n  \"tags\": [\"docker-compose\", \"docker\", \"devops\"],\n  \"canonical_url\": \"https://sevic.dev/notes/docker-compose-overview/\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Docker Compose runs multi-container applications from a single YAML file. One command can start an API, a database, a message broker, and supporting tools for local development - without installing each service on the host machine.\"), mdx(\"p\", null, \"This post covers Compose concepts and commands. For ready-made stacks, see the service-specific posts linked at the end (Postgres/Redis, RabbitMQ, MongoDB, Kafka, DynamoDB/SQS).\"), mdx(\"h3\", {\n    \"id\": \"prerequisites\"\n  }, \"Prerequisites\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"https://docs.docker.com/engine/install/\"\n  }), \"Docker Engine\"), \" installed\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Compose V2 - use \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"docker compose\"), \" (with a space). Current Docker Desktop includes it; no separate Compose install is required.\")), mdx(\"h3\", {\n    \"id\": \"mental-model\"\n  }, \"Mental model\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Project\"), \" - the folder that contains \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"docker-compose.yml\"), \". The project name defaults to the directory name and prefixes container names.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Services\"), \" - named containers defined in the file (\", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"api\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"redis\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"postgres\"), \"). Each service maps to one image or build context.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Network\"), \" - Compose creates a default network so services resolve each other by name. From the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"api\"), \" container, Redis is reachable at \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"redis:6379\"), \", not \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"localhost:6379\"), \".\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Volumes\"), \" - named or bind mounts for data that survives \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"docker compose down\"), \" (unless you pass \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"-v\"), \").\")), mdx(\"h3\", {\n    \"id\": \"minimal-compose-file\"\n  }, \"Minimal compose file\"), mdx(\"p\", null, \"A two-service stack: a Node API and Redis. No top-level \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"version:\"), \" key - it is deprecated in the current Compose specification.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-yml\"\n  }), \"services:\\n  api:\\n    build: .\\n    ports:\\n      - 3000:3000\\n    environment:\\n      REDIS_URL: redis://redis:6379\\n    depends_on:\\n      - redis\\n\\n  redis:\\n    image: redis:alpine\\n    volumes:\\n      - redis-data:/data\\n\\nvolumes:\\n  redis-data:\\n\")), mdx(\"p\", null, \"Run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"docker compose up --build\"), \" from the directory that contains this file.\"), mdx(\"h3\", {\n    \"id\": \"core-concepts\"\n  }, \"Core concepts\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Ports\"), \" - map host ports to container ports as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"host:container\"), \":\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-yml\"\n  }), \"ports:\\n  - 3000:3000\\n\")), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Environment\"), \" - inline variables or an env file:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-yml\"\n  }), \"environment:\\n  REDIS_URL: redis://redis:6379\\n\\nenv_file:\\n  - .env\\n\")), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Volumes\"), \" - \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"named volumes\"), \" are managed by Docker (good for database data). \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Bind mounts\"), \" map a host path into the container (good for live code reload during development):\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-yml\"\n  }), \"volumes:\\n  - redis-data:/data        # named\\n  - ./src:/app/src:ro       # bind mount\\n\")), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Networks\"), \" - services on the default network can reach each other by service name. Custom networks isolate groups of services (see the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/postgres-redis-docker-compose/\"\n  }), \"Postgres and Redis post\"), \" for a multi-network example).\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"depends_on\"), \" - controls startup order. It does not wait for the dependency to be ready; add a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"healthcheck\"), \" or retry logic in the app when you need readiness.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"restart\"), \" - policies like \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"on-failure:3\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"unless-stopped\"), \" keep containers running after crashes or host reboots.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"healthcheck\"), \" - optional probe so Compose and other services know when a container is ready:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-yml\"\n  }), \"healthcheck:\\n  test: ['CMD', 'redis-cli', 'ping']\\n  interval: 5s\\n  timeout: 3s\\n  retries: 5\\n\")), mdx(\"h3\", {\n    \"id\": \"commands\"\n  }, \"Commands\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Command\"), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Purpose\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose up\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Start services (foreground, logs in terminal)\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose up -d\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Start in detached mode\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose up --build\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Rebuild images before starting\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose down\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Stop and remove containers\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose down -v\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Also remove named volumes\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose ps\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"List running services\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose logs -f api\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Follow logs for one service\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose exec api sh\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Open a shell in a running container\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker compose pull\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Pull latest images\")))), mdx(\"h3\", {\n    \"id\": \"when-to-use-what\"\n  }, \"When to use what\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Tool\"), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Best for\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"docker run\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"One-off containers, quick image tests\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Docker Compose\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Local multi-service stacks, dev databases and queues\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Kubernetes\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Production orchestration, scaling, rolling deploys\")))), mdx(\"h3\", {\n    \"id\": \"service-specific-setups\"\n  }, \"Service-specific setups\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/postgres-redis-docker-compose/\"\n  }), \"Postgres and Redis containers with Docker Compose\"), \" - databases with Pgweb and Redis Commander\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/rabbitmq-docker-compose/\"\n  }), \"RabbitMQ container with Docker Compose\"), \" - message broker with management UI\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/mongodb-docker-compose/\"\n  }), \"MongoDB containers with Docker Compose\"), \" - MongoDB with Mongo Express\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/kafka-docker-compose/\"\n  }), \"Kafka containers with Docker Compose\"), \" - KRaft-mode Kafka with Kafka UI\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", _extends({\n    parentName: \"li\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/dynamodb-sqs-docker-compose/\"\n  }), \"DynamoDB and SQS containers with Docker Compose\"), \" - DynamoDB Local and ElasticMQ\")), mdx(\"h3\", {\n    \"id\": \"demo\"\n  }, \"Demo\"), mdx(\"p\", null, \"Runnable files for this post live in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"docker-compose-overview-demo\"), \" folder. Get access via \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/demos\"\n  }), \"code demos\"), \".\"));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"id":"16a6b8f0-569b-599f-8b57-8fa27ad43c1b"}},"staticQueryHashes":["1961101537","2542493696"]}