Skip to content

Commit

Permalink
feat: merge front and server dockerfiles and optimize build (#4589)
Browse files Browse the repository at this point in the history
* feat: merge front and server dockerfiles and optimize build

* fix: update image label

* fix: bring back support for REACT_APP_SERVER_BASE_URL injection at runtime

* fix: remove old entries & add nx cache in dockerignore

* feat: generate frontend config at runtime using Nest

* fix: format and filename

* feat: use the EnvironmentService and leave default blank

* feat: add support for DB migrations
  • Loading branch information
Freebios authored Mar 21, 2024
1 parent 3fa8c4b commit 1aa48d3
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 3 deletions.
6 changes: 4 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
server/node_modules/
server/.env
.git
.env
node_modules
.nx/cache
6 changes: 6 additions & 0 deletions packages/twenty-docker/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ prod-docs-build:
prod-docs-run:
@docker run -d -p 3000:3000 --name twenty-docs twenty-docs

prod-build:
@cd ../.. && docker build -f ./packages/twenty-docker/prod/twenty/Dockerfile --tag twenty . && cd -

prod-run:
@docker run -d -p 3000:3000 --name twenty twenty

prod-front-build:
@cd ../.. && docker build -f ./packages/twenty-docker/prod/twenty-front/Dockerfile --tag twenty-front . && cd -

Expand Down
77 changes: 77 additions & 0 deletions packages/twenty-docker/prod/twenty/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Base image for common dependencies
FROM node:18.17.1-alpine as common-deps

WORKDIR /app

# Copy only the necessary files for dependency resolution
COPY ./package.json ./yarn.lock ./.yarnrc.yml ./tsconfig.base.json ./nx.json /app/
COPY ./.yarn/releases /app/.yarn/releases

COPY ./packages/twenty-emails/package.json /app/packages/twenty-emails/
COPY ./packages/twenty-server/package.json /app/packages/twenty-server/
COPY ./packages/twenty-server/patches /app/packages/twenty-server/patches
COPY ./packages/twenty-ui/package.json /app/packages/twenty-ui/
COPY ./packages/twenty-front/package.json /app/packages/twenty-front/

# Install all dependencies
RUN yarn && yarn cache clean && npx nx reset


# Build the back
FROM common-deps as twenty-server-build

# Copy sourcecode after installing dependences to accelerate subsequents builds
COPY ./packages/twenty-emails /app/packages/twenty-emails
COPY ./packages/twenty-server /app/packages/twenty-server

RUN npx nx run twenty-server:build && \
mv /app/packages/twenty-server/dist /app/packages/twenty-server/build && \
npx nx run twenty-server:build:packageJson && \
mv /app/packages/twenty-server/dist/package.json /app/packages/twenty-server/package.json && \
rm -rf /app/packages/twenty-server/dist && \
mv /app/packages/twenty-server/build /app/packages/twenty-server/dist

RUN yarn workspaces focus --production twenty-emails twenty-server


# Build the front
FROM common-deps as twenty-front-build

ARG REACT_APP_SERVER_BASE_URL

COPY ./packages/twenty-front /app/packages/twenty-front
COPY ./packages/twenty-ui /app/packages/twenty-ui
RUN yarn nx build twenty-front


# Final stage: Run the application
FROM node:18.17.1-alpine as twenty

# Used to run healthcheck in docker
RUN apk add --no-cache curl jq

COPY ./packages/twenty-docker/prod/twenty/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh

WORKDIR /app/packages/twenty-server

ARG REACT_APP_SERVER_BASE_URL
ENV REACT_APP_SERVER_BASE_URL $REACT_APP_SERVER_BASE_URL

# Copy built applications from previous stages
COPY --chown=1000 --from=twenty-server-build /app /app
COPY --chown=1000 --from=twenty-server-build /app/packages/twenty-server /app/packages/twenty-server
COPY --chown=1000 --from=twenty-front-build /app/packages/twenty-front/build /app/packages/twenty-server/dist/front

# Set metadata and labels
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the backend and frontend, ensuring it deploys faster and runs the same way regardless of the deployment environment."

RUN mkdir /app/.local-storage
RUN chown -R 1000 /app

# Use non root user with uid 1000
USER 1000

CMD ["node", "dist/src/main"]
ENTRYPOINT ["/app/entrypoint.sh"]
17 changes: 17 additions & 0 deletions packages/twenty-docker/prod/twenty/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/sh

# Check if the initialization has already been done and that we enabled automatic migration
if [ "${ENABLE_DB_MIGRATIONS}" = "true" ] && [ ! -f /app/${STORAGE_LOCAL_PATH}/db_initialized ]; then
echo "Running database setup and migrations..."

# Run setup and migration scripts
npx ts-node ./scripts/setup-db.ts
yarn database:migrate:prod

# Mark initialization as done
echo "Successfuly migrated DB!"
touch /app/${STORAGE_LOCAL_PATH}/db_initialized
fi

# Continue with the original Docker command
exec "$@"
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ This should work out of the box with the eslint extension installed. If this doe
"source.fixAll.eslint": "explicit"
}
```

## Docker container build

To successfully build Docker images, ensure that your system has a minimum of 2GB of memory available. For users of Docker Desktop, please verify that you've allocated sufficient resources to Docker within the application's settings.
3 changes: 2 additions & 1 deletion packages/twenty-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"graphql-middleware": "^6.1.35",
"jwt-decode": "^4.0.0",
"passport": "^0.7.0",
"psl": "^1.9.0"
"psl": "^1.9.0",
"tsconfig-paths": "^4.2.0"
},
"devDependencies": {
"@nestjs/cli": "10.3.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/twenty-server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import '@sentry/tracing';

import { AppModule } from './app.module';

import { generateFrontConfig } from './utils/generate-front-config';
import { settings } from './engine/constants/settings';
import { LoggerService } from './engine/integrations/logger/logger.service';
import { EnvironmentService } from './engine/integrations/environment/environment.service';
Expand Down Expand Up @@ -60,6 +61,9 @@ const bootstrap = async () => {
}),
);

// Create the env-config.js of the front at runtime
generateFrontConfig();

await app.listen(app.get(EnvironmentService).get('PORT'));
};

Expand Down
31 changes: 31 additions & 0 deletions packages/twenty-server/src/utils/generate-front-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as fs from 'fs';
import * as path from 'path';

import { ConfigService } from '@nestjs/config';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';

const environmentService = new EnvironmentService(new ConfigService());

export function generateFrontConfig(): void {
const configObject = {
window: {
_env_: {
REACT_APP_SERVER_BASE_URL: environmentService.get('SERVER_URL'),
},
},
};

const configString = `window._env_ = ${JSON.stringify(
configObject.window._env_,
null,
2,
)};`;

const distPath = path.join(__dirname, '../..', 'front');

if (!fs.existsSync(distPath)) {
fs.mkdirSync(distPath, { recursive: true });
}

fs.writeFileSync(path.join(distPath, 'env-config.js'), configString, 'utf8');
}
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -45763,6 +45763,7 @@ __metadata:
passport: "npm:^0.7.0"
psl: "npm:^1.9.0"
rimraf: "npm:^5.0.5"
tsconfig-paths: "npm:^4.2.0"
typescript: "npm:^5.3.3"
languageName: unknown
linkType: soft
Expand Down

0 comments on commit 1aa48d3

Please sign in to comment.