mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-19 07:36:52 +00:00
fix: Remove isolated-vm from Dockerfile npm rebuild (#26745)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
name: 'Docker Build Smoke Test'
|
||||
|
||||
# Verifies the full Docker build chain works without any caching.
|
||||
# Catches native module compilation failures (e.g., isolated-vm, sqlite3)
|
||||
# that layer caching can mask in the regular E2E pipeline.
|
||||
#
|
||||
# Full chain: pnpm install → pnpm build (no Turbo cache) →
|
||||
# build base image (no Docker cache) →
|
||||
# build n8n + runners images (no Docker cache)
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docker/images/n8n/**'
|
||||
- 'docker/images/n8n-base/**'
|
||||
- 'docker/images/runners/**'
|
||||
- 'scripts/build-n8n.mjs'
|
||||
- 'scripts/dockerize-n8n.mjs'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
docker-smoke-test:
|
||||
name: 'Docker Build (no cache)'
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2204
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to DHI Registry (for base image)
|
||||
uses: ./.github/actions/docker-registry-login
|
||||
with:
|
||||
login-ghcr: 'false'
|
||||
login-dhi: 'true'
|
||||
dockerhub-username: ${{ secrets.DOCKER_USERNAME }}
|
||||
dockerhub-password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build full chain (no cache)
|
||||
uses: ./.github/actions/setup-nodejs
|
||||
with:
|
||||
build-command: 'pnpm build:docker:clean'
|
||||
enable-docker-cache: true
|
||||
|
||||
- name: Verify n8n image starts
|
||||
run: |
|
||||
docker run --rm -d --name n8n-smoke-test n8nio/n8n:local
|
||||
sleep 5
|
||||
docker logs n8n-smoke-test 2>&1 | tail -20
|
||||
docker stop n8n-smoke-test
|
||||
@@ -15,7 +15,7 @@ COPY ./compiled /usr/local/lib/node_modules/n8n
|
||||
COPY docker/images/n8n/docker-entrypoint.sh /
|
||||
|
||||
RUN cd /usr/local/lib/node_modules/n8n && \
|
||||
npm rebuild sqlite3 isolated-vm && \
|
||||
npm rebuild sqlite3 && \
|
||||
ln -s /usr/local/lib/node_modules/n8n/bin/n8n /usr/local/bin/n8n && \
|
||||
mkdir -p /home/node/.n8n && \
|
||||
chown -R node:node /home/node && \
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"build:docker": "node scripts/build-n8n.mjs && node scripts/dockerize-n8n.mjs",
|
||||
"build:docker:coverage": "BUILD_WITH_COVERAGE=true node scripts/build-n8n.mjs && node scripts/dockerize-n8n.mjs",
|
||||
"build:docker:scan": "node scripts/build-n8n.mjs && node scripts/dockerize-n8n.mjs && node scripts/scan-n8n-image.mjs",
|
||||
"build:docker:clean": "TURBO_FORCE=true node scripts/build-n8n.mjs && DOCKER_BUILD_NO_CACHE=true DOCKER_BUILD_BASE_IMAGE=true node scripts/dockerize-n8n.mjs",
|
||||
"build:docker:test": "node scripts/build-n8n.mjs && node scripts/dockerize-n8n.mjs && turbo run test:container:standard --filter=n8n-playwright",
|
||||
"typecheck": "turbo typecheck",
|
||||
"dev": "turbo run dev --parallel --env-mode=loose --filter=!@n8n/design-system --filter=!@n8n/chat --filter=!@n8n/task-runner",
|
||||
|
||||
@@ -119,7 +119,17 @@ const __dirname = path.dirname(__filename);
|
||||
const isInScriptsDir = path.basename(__dirname) === 'scripts';
|
||||
const rootDir = isInScriptsDir ? path.join(__dirname, '..') : __dirname;
|
||||
|
||||
const noCache = process.env.DOCKER_BUILD_NO_CACHE === 'true';
|
||||
const withBaseImage = process.env.DOCKER_BUILD_BASE_IMAGE === 'true';
|
||||
const nodeVersion = process.env.NODE_VERSION || '24.13.1';
|
||||
|
||||
const config = {
|
||||
base: {
|
||||
dockerfilePath: path.join(rootDir, 'docker/images/n8n-base/Dockerfile'),
|
||||
get fullImageName() {
|
||||
return `n8nio/base:${nodeVersion}`;
|
||||
},
|
||||
},
|
||||
n8n: {
|
||||
dockerfilePath: path.join(rootDir, 'docker/images/n8n/Dockerfile'),
|
||||
imageBaseName: process.env.IMAGE_BASE_NAME || 'n8nio/n8n',
|
||||
@@ -153,20 +163,35 @@ async function main() {
|
||||
echo(`INFO: n8n Image: ${config.n8n.fullImageName}`);
|
||||
echo(`INFO: Runners Image: ${config.runners.fullImageName}`);
|
||||
echo(`INFO: Platform: ${platform}`);
|
||||
if (noCache) echo(chalk.yellow('INFO: Docker layer cache disabled (DOCKER_BUILD_NO_CACHE=true)'));
|
||||
if (withBaseImage) echo(chalk.yellow('INFO: Building base image first (DOCKER_BUILD_BASE_IMAGE=true)'));
|
||||
echo(chalk.gray('-'.repeat(47)));
|
||||
|
||||
await checkPrerequisites();
|
||||
|
||||
if (withBaseImage) {
|
||||
await buildDockerImage({
|
||||
name: 'base',
|
||||
dockerfilePath: config.base.dockerfilePath,
|
||||
fullImageName: config.base.fullImageName,
|
||||
buildArgs: [`NODE_VERSION=${nodeVersion}`],
|
||||
});
|
||||
}
|
||||
|
||||
const nodeVersionArgs = withBaseImage ? [`NODE_VERSION=${nodeVersion}`] : [];
|
||||
|
||||
const n8nBuildTime = await buildDockerImage({
|
||||
name: 'n8n',
|
||||
dockerfilePath: config.n8n.dockerfilePath,
|
||||
fullImageName: config.n8n.fullImageName,
|
||||
buildArgs: nodeVersionArgs,
|
||||
});
|
||||
|
||||
const runnersBuildTime = await buildDockerImage({
|
||||
name: 'runners',
|
||||
dockerfilePath: config.runners.dockerfilePath,
|
||||
fullImageName: config.runners.fullImageName,
|
||||
buildArgs: nodeVersionArgs,
|
||||
});
|
||||
|
||||
// Get image details
|
||||
@@ -226,13 +251,18 @@ async function checkPrerequisites() {
|
||||
}
|
||||
}
|
||||
|
||||
async function buildDockerImage({ name, dockerfilePath, fullImageName }) {
|
||||
async function buildDockerImage({ name, dockerfilePath, fullImageName, buildArgs = [] }) {
|
||||
const startTime = Date.now();
|
||||
const containerEngine = await getContainerEngine();
|
||||
// Push directly if image name contains a registry (e.g., ghcr.io/...)
|
||||
// This avoids the slow --load step (export/import tarball) when pushing to a registry
|
||||
const shouldPush = fullImageName.includes('/') && fullImageName.split('/').length > 2;
|
||||
|
||||
const extraFlags = [
|
||||
...buildArgs.flatMap((arg) => ['--build-arg', arg]),
|
||||
...(noCache ? ['--no-cache'] : []),
|
||||
];
|
||||
|
||||
echo(chalk.yellow(`INFO: Building ${name} Docker image using ${containerEngine}...`));
|
||||
if (shouldPush) {
|
||||
echo(chalk.yellow(`INFO: Registry detected - pushing directly to ${fullImageName}`));
|
||||
@@ -243,6 +273,7 @@ async function buildDockerImage({ name, dockerfilePath, fullImageName }) {
|
||||
const { stdout } = await $`podman build \
|
||||
--platform ${platform} \
|
||||
--build-arg TARGETPLATFORM=${platform} \
|
||||
${extraFlags} \
|
||||
-t ${fullImageName} \
|
||||
-f ${dockerfilePath} \
|
||||
${config.buildContext}`;
|
||||
@@ -256,6 +287,7 @@ async function buildDockerImage({ name, dockerfilePath, fullImageName }) {
|
||||
const { stdout } = await $`docker buildx build \
|
||||
--platform ${platform} \
|
||||
--build-arg TARGETPLATFORM=${platform} \
|
||||
${extraFlags} \
|
||||
-t ${fullImageName} \
|
||||
-f ${dockerfilePath} \
|
||||
--provenance=false \
|
||||
|
||||
Reference in New Issue
Block a user