mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
fix(images): minimize ql3 runtime base
This commit is contained in:
@@ -517,8 +517,10 @@ function assertExactExternalClosure(readFile, root, findings) {
|
||||
}
|
||||
|
||||
function assertDockerfile(readFile, root, findings) {
|
||||
const pinnedNodeBase =
|
||||
const pinnedBuildNodeBase =
|
||||
'node:24.18.0-bookworm-slim@sha256:6f7b03f7c2c8e2e784dcf9295400527b9b1270fd37b7e9a7285cf83b6951452d';
|
||||
const pinnedRuntimeNodeBase =
|
||||
'node:24.18.0-alpine3.23@sha256:595398b0081eacda8e1c4c5b97b76cd1020e4d58a8ebcb4843b9bca1e79e7436';
|
||||
const dockerfile = readFile(
|
||||
path.join(root, 'deploy/containers/ql3-cluster-control/Dockerfile'),
|
||||
'utf8',
|
||||
@@ -596,11 +598,16 @@ function assertDockerfile(readFile, root, findings) {
|
||||
),
|
||||
);
|
||||
}
|
||||
if (dockerfile.split(`FROM ${pinnedNodeBase}`).length - 1 !== 2) {
|
||||
if (
|
||||
!dockerfile.includes(
|
||||
`FROM ${pinnedBuildNodeBase} AS dependency-manifest`,
|
||||
) ||
|
||||
!dockerfile.includes(`FROM ${pinnedRuntimeNodeBase} AS runtime-base`)
|
||||
) {
|
||||
findings.push(
|
||||
finding(
|
||||
'QL3_CLUSTER_DOCKERFILE_BASE_IMAGE_NOT_PINNED',
|
||||
'Cluster control build and runtime stages must use the exact immutable Node base digest',
|
||||
'Cluster control build and runtime stages must use their exact immutable Node base digests',
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -652,11 +659,16 @@ function assertDockerfile(readFile, root, findings) {
|
||||
);
|
||||
}
|
||||
}
|
||||
if (adminDockerfile.split(`FROM ${pinnedNodeBase}`).length - 1 !== 2) {
|
||||
if (
|
||||
!adminDockerfile.includes(
|
||||
`FROM ${pinnedBuildNodeBase} AS dependency-manifest`,
|
||||
) ||
|
||||
!adminDockerfile.includes(`FROM ${pinnedRuntimeNodeBase} AS runtime`)
|
||||
) {
|
||||
findings.push(
|
||||
finding(
|
||||
'QL3_CLUSTER_ADMIN_DOCKERFILE_BASE_IMAGE_NOT_PINNED',
|
||||
'Cluster admin build and runtime stages must use the exact immutable Node base digest',
|
||||
'Cluster admin build and runtime stages must use their exact immutable Node base digests',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ const { readReleaseIdentity } = require('./lib/ql3-release-identity.cjs');
|
||||
|
||||
const IMAGE_DIRECTORY = 'deploy/containers/ql3-local-application';
|
||||
const QL3_VERSION = readReleaseIdentity(path.resolve(__dirname, '..')).version;
|
||||
const NODE_IMAGE =
|
||||
const BUILD_NODE_IMAGE =
|
||||
'node:24.18.0-bookworm-slim@sha256:6f7b03f7c2c8e2e784dcf9295400527b9b1270fd37b7e9a7285cf83b6951452d';
|
||||
const RUNTIME_NODE_IMAGE =
|
||||
'node:24.18.0-alpine3.23@sha256:595398b0081eacda8e1c4c5b97b76cd1020e4d58a8ebcb4843b9bca1e79e7436';
|
||||
const BUILD_DEPENDENCIES = Object.freeze({
|
||||
croner: '7.0.8',
|
||||
'drizzle-orm': '1.0.0-rc.4',
|
||||
@@ -169,14 +171,26 @@ function counts(values) {
|
||||
}
|
||||
|
||||
function auditDockerfile(contents, findings) {
|
||||
const exactBasePattern = new RegExp(
|
||||
`^FROM ${NODE_IMAGE.replace(
|
||||
/[.*+?^${}()|[\]\\]/g,
|
||||
'\\$&',
|
||||
)} AS (?:dependency-manifest|runtime)$`,
|
||||
const escapedBuildNodeImage = BUILD_NODE_IMAGE.replace(
|
||||
/[.*+?^${}()|[\]\\]/g,
|
||||
'\\$&',
|
||||
);
|
||||
const escapedRuntimeNodeImage = RUNTIME_NODE_IMAGE.replace(
|
||||
/[.*+?^${}()|[\]\\]/g,
|
||||
'\\$&',
|
||||
);
|
||||
const exactBuildBasePattern = new RegExp(
|
||||
`^FROM ${escapedBuildNodeImage} AS dependency-manifest$`,
|
||||
'gm',
|
||||
);
|
||||
if ([...contents.matchAll(exactBasePattern)].length !== 2) {
|
||||
const exactRuntimeBasePattern = new RegExp(
|
||||
`^FROM ${escapedRuntimeNodeImage} AS runtime$`,
|
||||
'gm',
|
||||
);
|
||||
if (
|
||||
[...contents.matchAll(exactBuildBasePattern)].length !== 1 ||
|
||||
[...contents.matchAll(exactRuntimeBasePattern)].length !== 1
|
||||
) {
|
||||
addFinding(findings, 'BASE_IMAGE_NOT_EXACTLY_PINNED');
|
||||
}
|
||||
if (/(?:^|\n)\s*ARG\s+NODE_IMAGE\b/.test(contents)) {
|
||||
@@ -323,7 +337,8 @@ function auditLocalImageContract(root) {
|
||||
return Object.freeze({
|
||||
schemaVersion: 1,
|
||||
image: 'local-application',
|
||||
nodeImage: NODE_IMAGE,
|
||||
nodeImage: RUNTIME_NODE_IMAGE,
|
||||
buildNodeImage: BUILD_NODE_IMAGE,
|
||||
runtimePackages: Object.freeze(
|
||||
[
|
||||
...RUNTIME_PACKAGES.map((name) => `@qinglong/${name.slice(4)}`),
|
||||
|
||||
@@ -78,6 +78,7 @@ const dockerfile = fs.readFileSync(
|
||||
);
|
||||
for (const required of [
|
||||
'node:24.18.0-bookworm-slim@sha256:',
|
||||
'node:24.18.0-alpine3.23@sha256:595398b0081eacda8e1c4c5b97b76cd1020e4d58a8ebcb4843b9bca1e79e7436',
|
||||
'npm ci --omit=dev --ignore-scripts',
|
||||
'packages/ql3-runtime-core',
|
||||
'packages/ql3-local-process',
|
||||
|
||||
Reference in New Issue
Block a user