medusajs / medusa

Building blocks for digital commerce
https://medusajs.com
MIT License
24.67k stars 2.43k forks source link

Docker build source files issue. API routes does not work. #9157

Open predaytor opened 2 days ago

predaytor commented 2 days ago

Bug report

Describe the bug

I'm deploying fly.io using a docker build, compared to version 1.0 there are a few issues with the same production image. The API routes don't work unless the /src folder is commited on the production server (these are typescript files, not sure why that seems necessary).

After running medusa build only the /build folder is created, /dist is missing for some reason. Running locally the build script outputs the /dist folder, so not sure about that behavior.

Also, in the latest medusa release, x-publishable-api-key seems to have no effect if we commit the /src folder to access API routes.

System information

Medusa version (including plugins): v2.0.9-preview Node.js version: 22 Database: Postgres (sslmode disable) Operating system: Linux Browser (if relevant): Chrome

Screenshots

HTTPie application log

Code snippets

Dockerfile:

FROM node:22-alpine AS base
LABEL fly_launch_runtime="Node.js"
WORKDIR /usr/src/app

# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat

# Install dependencies only when needed
FROM base AS deps

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./

RUN \
  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
  else echo "Lockfile not found." && exit 1; \
  fi

# Rebuild the source code only when needed
FROM base AS builder

ENV NODE_ENV production

COPY --from=deps /usr/src/app/node_modules ./node_modules
COPY . .

RUN \
  if [ -f yarn.lock ]; then yarn run build; \
  elif [ -f package-lock.json ]; then npm run build; \
  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
  else echo "Lockfile not found." && exit 1; \
  fi

# Final stage for app image
FROM base as runner

# Setting NODE_ENV=production requires secure cookie (https only access)
ENV NODE_ENV production
ENV PORT 9000
ENV HOST 0.0.0.0

# Copy config file
COPY ./medusa-config.js ./

# Copy built application
COPY --from=builder /usr/src/app/package.json ./package.json
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/build ./build

# Run application
EXPOSE 9000
CMD ["npm", "run", "start"]

fixed Dockerfile last stage:

# Final stage for app image
FROM base as runner

...

# Source files?
COPY ./src ./src

...

# ! `/dist` folder does not exist at builder stage (compared to medusa 1.0 version)
# COPY --from=builder /usr/src/app/dist ./dist

# Run application
EXPOSE 9000
CMD ["npm", "run", "start"]
predaytor commented 2 days ago

Also, after converting the config to the ES module, it doesn't seem to work in production (e.g. npx medusa db:migrate). Running locally works fine. It would be nice to have more info on how to properly bundle an app with Docker.

Error in loading config: This is caused by either a bug in Node.js or incorrect usage of Node.js internals.

before:

const { loadEnv, defineConfig, Modules } = require("@medusajs/utils");

loadEnv(process.env.NODE_ENV, process.cwd());

const config = defineConfig({
  projectConfig: {
    // ...
  },

  // ...
});

module.exports = config;

after:

import { loadEnv, defineConfig, Modules } from "@medusajs/utils";

loadEnv(process.env.NODE_ENV, process.cwd());

const config = defineConfig({
  projectConfig: {
    // ...
  },

  // ...
});

export default config;
thetutlage commented 1 day ago

Hey, it seems you are not copying the dist folder in the following copy commands.

COPY --from=builder /usr/src/app/package.json ./package.json
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/build ./build
predaytor commented 1 day ago

@thetutlage yeah, for some reason it wasn't generated with the /build folder, not sure why. Medusa 1.0 and the running locally Medusa 2.0 build script work fine. Maybe something wrong with default typescript configuration?

predaytor commented 23 hours ago

It seems to work using similar setup for scripts from Medusa 1.0.

"scripts": {
  "clean": "cross-env ./node_modules/.bin/rimraf dist",
  "build": "cross-env npm run clean && medusa build && tsc -p tsconfig.json",
}

But without copying the ./src folder to the docker image, the API routes don't work:

Cannot GET /store/custom

Maybe we should do like this?

COPY --from=builder /usr/src/app/dist ./src