UNPKG

scandium

Version:

> Easily deploy any Node.js web server to AWS Lambda.

98 lines (82 loc) 4.63 kB
const githubPublicKey = 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' const sshPostfix = ' && unlink $HOME/.ssh/id_rsa && unlink $HOME/.ssh/id_rsa.pub' const sshPrefix = 'echo $SSH_PRIVATE_KEY | base64 --decode > $HOME/.ssh/id_rsa && chmod 0600 $HOME/.ssh/id_rsa && echo $SSH_PUBLIC_KEY | base64 --decode > $HOME/.ssh/id_rsa.pub && ' const listNpmPackFiles = ( // Run "npm pack" and parse output 'JSON.parse(child_process.execSync("npm pack --dry-run --json").toString())' + // Extract list of files from output '[0].files.map(file => file.path)' + // Remove "scandium-entrypoint.mjs" if it exists '.filter(path => path !== "scandium-entrypoint.mjs")' + // Always add back "scandium-entrypoint.mjs" '.concat(["scandium-entrypoint.mjs"])' + // Output one line per file '.join("\\n")' ) /** * @param {object} options * @param {string | null} options.directory * @param {boolean} options.hasBuildScript * @param {boolean} options.hasPrepareScript * @param {boolean} options.hasProductionDependencies * @param {boolean} options.skipNodeModules * @param {boolean} options.sshKey * @param {boolean} options.yarn * @returns {string} */ export function generateDockerfile (options) { const { hasBuildScript, hasPrepareScript, hasProductionDependencies, skipNodeModules, sshKey, yarn } = options const lines = [] // Base image on Amazon Linux lines.push('FROM public.ecr.aws/lambda/nodejs:22.2025.05.04.04') // Install prerequisites lines.push('RUN dnf install -y gcc gcc-c++ git make openssl-devel tar zip') // Install package managers if (yarn) lines.push('RUN npm install -g yarn@1.22.22') // Set the workdir to same directory as Lambdas executes in // Some tools, e.g. Next.js, hard codes the path during the build phase. let directoryPrefix = '' if (options.directory) { lines.push(`WORKDIR /var/task/${options.directory}`) directoryPrefix = `${options.directory}/` } else { lines.push('WORKDIR /var/task') } // Add build argument for SSH key, and prime known_hosts with GitHub public key if (sshKey) lines.push('ARG SSH_PRIVATE_KEY', 'ARG SSH_PUBLIC_KEY', `RUN mkdir -p $HOME/.ssh && echo "${githubPublicKey}" >> $HOME/.ssh/known_hosts`) // Mount stripped package files // These files have the version stripped, so that docker can cache better. // Stripping is not needed on the yarn lockfile, as that doesn't include pacakge version. const packageFileMounts = [ `--mount=type=bind,source=${directoryPrefix}scandium-clean-package.json,target=package.json`, `--mount=type=bind,source=${directoryPrefix}${yarn ? 'yarn.lock' : 'scandium-clean-package-lock.json'},target=${yarn ? 'yarn.lock' : 'package-lock.json'}` ].join(' ') // Add production dependencies // This step is run before adding the code, to increase docker cache use. if (hasProductionDependencies && !skipNodeModules) lines.push(`RUN ${packageFileMounts} ${sshKey ? sshPrefix : ''}${yarn ? 'yarn install --production --frozen-lockfile' : 'npm ci --production'}${sshKey ? sshPostfix : ''}`) if (hasProductionDependencies && !skipNodeModules) lines.push('RUN zip -9qyr /output.zip node_modules') // Install dev-dependencies, if there is a `prepare` or `build` script present if (hasPrepareScript || hasBuildScript) lines.push(`RUN ${packageFileMounts} ${sshKey ? sshPrefix : ''}${yarn ? 'yarn install --frozen-lockfile' : 'npm ci'}${sshKey ? sshPostfix : ''}`) // Add the app files, and remove our special files if (options.directory) { lines.push('WORKDIR /var/task') lines.push('COPY . .') lines.push(`WORKDIR /var/task/${options.directory}`) } else { lines.push('COPY . .') } if (yarn) { lines.push('RUN rm scandium-clean-package.json') } else { lines.push('RUN rm scandium-clean-package.json scandium-clean-package-lock.json') } // Run the `prepare` or `build` script, if present if (hasPrepareScript) lines.push('RUN npm run-script prepare') else if (hasBuildScript) lines.push('RUN npm run-script build') // Add the local code to the zip lines.push(`RUN node -p '${listNpmPackFiles}' | zip -9qyrg@ /output.zip`) // Give the zip to the caller lines.push('ENTRYPOINT []') lines.push('CMD cat /output.zip | base64') return lines.join('\n') }