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:
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:
- Change the
packageManagerfield inpackage.jsonto your preferred package manager, such asnpm@{version}oryarn@{version}, where{version}is the version of the package manager you have installed. - Add a
workspacesfield inpackage.jsonwith the following content:
- Remove the
node_modulesdirectory andpnpm-lock.yamlandpnpm-workspace.yamlfiles. - If you're using
yarn, add a.yarnrc.ymlfile with the following content:
- If you're using
npm, add anoverridesfield inpackage.json:
- Install dependencies with your preferred package manager to generate the appropriate lock file (
package-lock.jsonfor npm oryarn.lockfor Yarn).
2. Create docker-compose.yml#
In the cloned repository, create a file named docker-compose.yml with the following content:
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/storefrontdirectory and thestorefrontservice from thedocker-compose.ymlfile.
- If you don't want to use the storefront, you can remove the
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_namefor each service to avoid conflicts.- For example, use
medusa_postgres_myproject,medusa_redis_myproject,medusa_backend_myproject, andmedusa_storefront_myprojectinstead of the current names.
- For example, use
- Change the volume names to avoid conflicts.
- For example, use
postgres_data_myprojectinstead ofpostgres_data.
- For example, use
- Change the network name to avoid conflicts.
- For example, use
medusa_network_myprojectinstead ofmedusa_network.
- For example, use
- 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.
- Use
- Update the
DATABASE_URLandREDIS_URLenvironment 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:
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:
Make sure to give both scripts executable permissions:
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.
/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:
Where:
docker:upstarts the development server in a Docker container as a background process.docker:downstops 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:
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:
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:
9. Create .env Files#
Create environment files for both the backend and storefront by copying from their templates.
Copy the backend template:
Copy the storefront template:
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:
Once you see the following message, the Medusa server and admin are ready:
You can now access the Medusa server at http://localhost:9000 and the Medusa Admin dashboard at http://localhost:9000/app.
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:
- Log in to the admin dashboard at
http://localhost:9000/app. - Go to Settings > API Key Management and create a new Publishable API Key.
- Add the key to
apps/storefront/.env:
- Restart the storefront service:
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:
Check the logs of the storefront:
Troubleshooting#
start.sh Not Found Error#
If you get the following error when starting the Medusa application with Docker:
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:
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:
to
Learn More about your Medusa Application#
You can learn more about your Medusa application and its setup in the Installation chapter.