1.2.1. Install Medusa with Docker

In this chapter, you'll learn how to install and run a Medusa application using Docker.

The main supported installation method is using create-medusa-app. However, since it requires prerequisites like PostgreSQL, Docker may be a preferred and easier option for some users. You can follow this guide to set up a Medusa application with Docker in this case.

You can follow this guide on any operating system that supports Docker, including Windows, macOS, and Linux.

1. Clone the DTC Starter Repository#

To get started, clone the DTC Starter repository:

Terminal
git clone https://github.com/medusajs/dtc-starter.git --depth=1 my-medusa-storecd my-medusa-store

This command clones the repository into a directory named my-medusa-store.

The rest of the steps are performed inside this directory.

Change Package Manager#

The project uses pnpm as the package manager, as declared in package.json.

To use a different package manager:

  1. Change the packageManager field in package.json to your preferred package manager, such as npm@{version} or yarn@{version}, where {version} is the version of the package manager you have installed.
  2. Add a workspaces field in package.json with the following content:
package.json
1{2  "workspaces": [3    "apps/*"4  ]5}
  1. Remove the node_modules directory and pnpm-lock.yaml and pnpm-workspace.yaml files.
  2. If you're using yarn, add a .yarnrc.yml file with the following content:
.yarnrc.yml
nodeLinker: node-modules
  1. If you're using npm, add an overrides field in package.json:
package.json
1{2  "overrides": {3    "ajv": "^8.0.0"4  }5}
  1. Install dependencies with your preferred package manager to generate the appropriate lock file (package-lock.json for npm or yarn.lock for Yarn).

2. Create docker-compose.yml#

In the cloned repository, create a file named docker-compose.yml with the following content:

docker-compose.yml
1services:2  # PostgreSQL Database3  postgres:4    image: postgres:15-alpine5    container_name: medusa_postgres6    restart: unless-stopped7    environment:8      POSTGRES_DB: medusa-store9      POSTGRES_USER: postgres10      POSTGRES_PASSWORD: postgres11    ports:12      - "5432:5432"13    volumes:14      - postgres_data:/var/lib/postgresql/data15    networks:16      - medusa_network17
18  # Redis19  redis:20    image: redis:7-alpine21    container_name: medusa_redis22    restart: unless-stopped23    ports:24      - "6379:6379"25    networks:26      - medusa_network27
28  # Medusa Server29  # This service runs the Medusa backend application30  # and the admin dashboard.31  medusa:32    build: .33    container_name: medusa_backend34    restart: unless-stopped35    depends_on:36      - postgres37      - redis38    ports:39      - "9000:9000"40      - "5173:5173"41    environment:42      - NODE_ENV=development43      - DATABASE_URL=postgres://postgres:postgres@postgres:5432/medusa-store44      - REDIS_URL=redis://redis:637945    env_file:46      - apps/backend/.env47    volumes:48      - .:/server49      - /server/node_modules50      - /server/apps/backend/node_modules51    networks:52      - medusa_network53
54  # Storefront55  # This service runs the Next.js Starter Storefront56  storefront:57    build: .58    container_name: medusa_storefront59    restart: unless-stopped60    depends_on:61      - medusa62    ports:63      - "8000:8000"64    environment:65      - NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://medusa:900066    env_file:67      - apps/storefront/.env68    volumes:69      - .:/server70      - /server/node_modules71      - /server/apps/backend/node_modules72      - /server/apps/storefront/node_modules73      - /server/apps/storefront/.next74    entrypoint: ["./start-storefront.sh"]75    networks:76      - medusa_network77
78volumes:79  postgres_data:80
81networks:82  medusa_network:83    driver: bridge

You define four services in this file:

  • postgres: The PostgreSQL database service that stores your Medusa application's data.
  • redis: The Redis service that stores session data.
  • medusa: The Medusa service that runs the server and the admin dashboard. It connects to the PostgreSQL and Redis services.
  • storefront: The Next.js Starter Storefront service. It connects to the Medusa service.
    • If you don't want to use the storefront, you can remove the apps/storefront directory and the storefront service from the docker-compose.yml file.

The env_file paths are relative to the project root: apps/backend/.env for the backend and apps/storefront/.env for the storefront.

The anonymous volumes for node_modules directories are required because pnpm workspaces create per-package node_modules directories with symlinks. Without these volumes, the Docker bind mount overwrites the installed dependencies.

Recommendations for Multiple Local Projects#

If this isn't the first Medusa project you're setting up with Docker on your machine, make sure to:

  • Change the container_name for each service to avoid conflicts.
    • For example, use medusa_postgres_myproject, medusa_redis_myproject, medusa_backend_myproject, and medusa_storefront_myproject instead of the current names.
  • Change the volume names to avoid conflicts.
    • For example, use postgres_data_myproject instead of postgres_data.
  • Change the network name to avoid conflicts.
    • For example, use medusa_network_myproject instead of medusa_network.
  • Change the ports to avoid conflicts with other projects. For example:
    • Use "5433:5432" for PostgreSQL.
    • Use "6380:6379" for Redis.
    • Use "9001:9000" for the Medusa server.
    • Use "5174:5173" for the Medusa Admin dashboard.
    • Use "8001:8000" for the storefront.
  • Update the DATABASE_URL and REDIS_URL environment variables accordingly.

3. Create start.sh#

Create a script file that runs database migrations and starts the Medusa development server.

Create the file start.sh with the following content:

Windows Users: Ensure that the start.sh file uses LF line endings instead of CRLF. Git on Windows can sometimes automatically convert line endings, which causes errors when running the script inside the Linux-based Docker container. Learn how to configure your environment to maintain LF line endings in this guide from GitHub.

4. Create start-storefront.sh#

Create a separate script for the storefront service:

Windows Users: Apply the same LF line endings requirement mentioned in the previous step to this file as well.

Make sure to give both scripts executable permissions:

Note: Setting permissions isn't necessary on Windows, but it's recommended to run this command on Unix-based systems like macOS and Linux.
Terminal
chmod +x start.sh start-storefront.sh

5. Create Dockerfile#

The Dockerfile defines how the Docker image is built. Both the medusa and storefront services reuse the same image — the storefront overrides the entrypoint in docker-compose.yml.

Create a file named Dockerfile with the following content:

In the Dockerfile, you use the node:20-alpine image as the base since Medusa requires Node.js v20 or later.

The workspace configuration files and all apps' package.json files are copied before installing dependencies so that the workspace dependency graph is resolved correctly. After installing dependencies, the rest of the source code is copied.

Note: While it's more common to use /app as the working directory, it's highly recommended to use /server for the Medusa service to avoid conflicts with Medusa Admin customizations. Learn more in this troubleshooting guide.

6. Update Scripts in package.json#

Update the scripts section in the root package.json file to start and stop the Docker services.

Add the following scripts:

package.json
1{2  "scripts": {3    // Other scripts...4    "docker:up": "docker compose up --build -d",5    "docker:down": "docker compose down"6  }7}

Where:

  • docker:up starts the development server in a Docker container as a background process.
  • docker:down stops and removes the Docker containers.

7. Update Medusa Configuration#

Disable SSL for PostgreSQL Connection#

If you try to run the Medusa application now with Docker, you'll encounter an SSL error as the server tries to connect to the PostgreSQL database.

To resolve the error, add the following configurations in apps/backend/medusa-config.ts:

apps/backend/medusa-config.ts
1import { loadEnv, defineConfig } from "@medusajs/framework/utils"2
3loadEnv(process.env.NODE_ENV || "development", process.cwd())4
5module.exports = defineConfig({6  projectConfig: {7    // ...8    databaseDriverOptions: {9      ssl: false,10      sslmode: "disable",11    },12  },13})

You add the projectConfig.databaseDriverOptions to disable SSL for the PostgreSQL database connection.

Add Vite Configuration for Medusa Admin#

To ensure that the Medusa Admin dashboard works correctly when running inside Docker, connects to the Medusa server, and reloads properly with Hot Module Replacement (HMR), add the following Vite configuration in apps/backend/medusa-config.ts:

apps/backend/medusa-config.ts
1module.exports = defineConfig({2  // ...3  admin: {4    vite: (config) => {5      return {6        server: {7          host: "0.0.0.0",8          // Allow all hosts when running in Docker (development mode)9          // In production, this should be more restrictive10          allowedHosts: [11            "localhost",12            ".localhost",13            "127.0.0.1",14          ],15          hmr: {16            // HMR websocket port inside container17            port: 5173,18            // Port browser connects to (exposed in docker-compose.yml)19            clientPort: 5173,20          },21        },22      }23    },24  },25})

You configure the Vite development server to listen on all network interfaces (0.0.0.0) and set up HMR to work correctly within the Docker environment.


8. Add .dockerignore#

To ensure only the necessary files are copied into the Docker image, create a .dockerignore file with the following content:

.dockerignore
1node_modules2apps/backend/node_modules3apps/storefront/node_modules4apps/backend/.medusa5apps/storefront/.next6npm-debug.log*7yarn-debug.log*8yarn-error.log*9.git10.gitignore11README.md12.env.test13.nyc_output14coverage15.DS_Store16*.log17dist18build

9. Create .env Files#

Create environment files for both the backend and storefront by copying from their templates.

Copy the backend template:

Terminal
cp apps/backend/.env.template apps/backend/.env

Copy the storefront template:

Terminal
cp apps/storefront/.env.template apps/storefront/.env

Update the values in each file as needed.


10. Start the Medusa Application with Docker#

All configurations are now ready. Start the Medusa application using Docker by running the following command:

Docker pulls the necessary images, starts the PostgreSQL and Redis services, builds the Medusa and storefront services, and runs them in Docker containers.

Check the logs to ensure everything is running smoothly:

Terminal
docker compose logs -f

Once you see the following message, the Medusa server and admin are ready:

Code
1✔ Server is ready on port: 9000 - 3ms2info:    Admin URL → http://localhost:9000/app

You can now access the Medusa server at http://localhost:9000 and the Medusa Admin dashboard at http://localhost:9000/app.

Did the Docker installation finish successfully?

Create Admin User and Configure Storefront#

Create Admin User#

To create an admin user, run the following command:

Replace admin@example.com and supersecret with your desired email and password.

You can now log in to the Medusa Admin dashboard at http://localhost:9000/app.

Set Publishable API Key for the Storefront#

The storefront requires a publishable API key to connect to the Medusa backend:

  1. Log in to the admin dashboard at http://localhost:9000/app.
  2. Go to Settings > API Key Management and create a new Publishable API Key.
  3. Add the key to apps/storefront/.env:
Terminal
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_...
  1. Restart the storefront service:
Terminal
docker compose up storefront -d
Note: The storefront requires this key at startup and exits with an error if it's missing.

Stop the Medusa Application Running in Docker#

To stop the Medusa application running in Docker, run the following command:

This command stops and removes the Docker containers created by the docker-compose.yml file.

This doesn't delete any data in your application or its database. Start the server again using the docker:up command.


Check Logs#

Check the logs of the Medusa backend running in Docker:

Terminal
docker compose logs -f medusa

Check the logs of the storefront:

Terminal
docker compose logs -f storefront

Troubleshooting#

start.sh Not Found Error#

If you get the following error when starting the Medusa application with Docker:

Terminal
medusa_backend exited with code 127 (restarting)medusa_backend   | /usr/local/bin/docker-entrypoint.sh: exec: line 11: ./start.sh: not found

This is a common error for Windows users. It usually occurs when the start.sh file uses CRLF line endings instead of LF.

To fix this, ensure that the start.sh file uses LF line endings. You can configure Git to maintain LF line endings by following this guide from GitHub.

Couldn't Find X File or Directory Errors#

If you encounter errors indicating that certain files or directories couldn't be found, make sure you're running the commands from the root directory of your Medusa application (the same directory where the docker-compose.yml file is located).

For example, if you run the docker:up command and see an error like this:

Terminal
error Couldn't find a package.json file in "/"

Ensure that your terminal's current working directory is the root of your Medusa application, then try running the command again.

Container Name Conflicts#

If you're running multiple Medusa projects with Docker or have previously run this guide, you may encounter container name conflicts.

To resolve this, ensure that the container_name values in your docker-compose.yml file are unique for each project. You can modify them by appending a unique identifier to each name.

For example, change:

docker-compose.yml
container_name: medusa_postgres

to

docker-compose.yml
container_name: medusa_postgres_myproject

Learn More about your Medusa Application#

You can learn more about your Medusa application and its setup in the Installation chapter.

Was this chapter helpful?
Ask Bloom
For assistance in your development, use Claude Code Plugins or Medusa MCP server in Cursor, VSCode, etc...FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break