From 4e44bf279db7434c09e655ca98cd8e184edda793 Mon Sep 17 00:00:00 2001 From: norbjd Date: Fri, 27 Jun 2025 15:35:36 +0200 Subject: [PATCH 1/2] fix(container): honor .dockerignore when building a container --- CHANGELOG.md | 6 +++++ deploy/lib/buildAndPushContainers.js | 35 +++++++++++++++++++++++++--- examples/go/package-lock.json | 5 ++-- package-lock.json | 7 +++--- package.json | 5 ++-- shared/api/utils.js | 2 +- tests/containers/containers.test.js | 5 +--- 7 files changed, 47 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 763986dd..01544de5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.4.16 + +### Fixed + +- Honor `.dockerignore` when building a container #277 + ## 0.4.15 ### Added diff --git a/deploy/lib/buildAndPushContainers.js b/deploy/lib/buildAndPushContainers.js index ecc4f69b..c4076c06 100644 --- a/deploy/lib/buildAndPushContainers.js +++ b/deploy/lib/buildAndPushContainers.js @@ -1,7 +1,8 @@ "use strict"; const Docker = require("dockerode"); -const tar = require("tar-fs"); +const path = require('path'); +const fs = require('fs'); const docker = new Docker(); @@ -44,6 +45,33 @@ function findErrorInBuildOutput(buildOutput) { } } +function getFilesInBuildContextDirectory(directory) { + let files = []; + + try { + const dirents = fs.readdirSync(directory, { withFileTypes: true }); + + dirents.forEach(dirent => { + const absolutePath = path.join(directory, dirent.name); + if (dirent.isDirectory()) { + const subFiles = getFilesInBuildContextDirectory(absolutePath); + + // Prepend the current directory name to each subfile path + const relativeSubFiles = subFiles.map(subFile => path.join(dirent.name, subFile)); + files = files.concat(relativeSubFiles); + } else if (dirent.isFile() && dirent.name !== '.dockerignore') { + // Don't include .dockerignore file in result + files.push(dirent.name); + } + } + ); + } catch (err) { + console.error(`Error reading directory ${directory}:`, err); + } + + return files; +} + module.exports = { async buildAndPushContainers() { // used for pushing @@ -71,7 +99,6 @@ module.exports = { if (container["directory"] === undefined) { return; } - const tarStream = tar.pack(`./${container.directory}`); const imageName = `${this.namespace.registry_endpoint}/${container.name}:latest`; this.serverless.cli.log( @@ -80,7 +107,9 @@ module.exports = { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { - const buildStream = await docker.buildImage(tarStream, { + let files = getFilesInBuildContextDirectory(container.directory); + + const buildStream = await docker.buildImage({context: container.directory, src: files}, { t: imageName, registryconfig: registryAuth, }); diff --git a/examples/go/package-lock.json b/examples/go/package-lock.json index e88fc0dd..6cd23724 100644 --- a/examples/go/package-lock.json +++ b/examples/go/package-lock.json @@ -13,7 +13,7 @@ } }, "../..": { - "version": "0.4.15", + "version": "0.4.16", "dev": true, "license": "MIT", "dependencies": { @@ -22,8 +22,7 @@ "axios": "^1.4.0", "bluebird": "^3.7.2", "dockerode": "^3.3.5", - "js-yaml": "^4.1.0", - "tar-fs": "^2.1.1" + "js-yaml": "^4.1.0" }, "devDependencies": { "@eslint/js": "^9.27.0", diff --git a/package-lock.json b/package-lock.json index 7f6de72e..f86ce7ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "serverless-scaleway-functions", - "version": "0.4.15", + "version": "0.4.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "serverless-scaleway-functions", - "version": "0.4.15", + "version": "0.4.16", "license": "MIT", "dependencies": { "@serverless/utils": "^6.13.1", @@ -14,8 +14,7 @@ "axios": "^1.4.0", "bluebird": "^3.7.2", "dockerode": "^4.0.6", - "js-yaml": "^4.1.0", - "tar-fs": "^2.1.1" + "js-yaml": "^4.1.0" }, "devDependencies": { "@eslint/js": "^9.27.0", diff --git a/package.json b/package.json index d1ab45fa..5c74b98f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-scaleway-functions", - "version": "0.4.15", + "version": "0.4.16", "description": "Provider plugin for the Serverless Framework v3.x which adds support for Scaleway Functions.", "main": "index.js", "author": "scaleway.com", @@ -57,8 +57,7 @@ "axios": "^1.4.0", "bluebird": "^3.7.2", "dockerode": "^4.0.6", - "js-yaml": "^4.1.0", - "tar-fs": "^2.1.1" + "js-yaml": "^4.1.0" }, "devDependencies": { "@eslint/js": "^9.27.0", diff --git a/shared/api/utils.js b/shared/api/utils.js index cb4299e3..69bfa5bd 100644 --- a/shared/api/utils.js +++ b/shared/api/utils.js @@ -1,7 +1,7 @@ const axios = require("axios"); const https = require("https"); -const version = "0.4.15"; +const version = "0.4.16"; const invalidArgumentsType = "invalid_arguments"; diff --git a/tests/containers/containers.test.js b/tests/containers/containers.test.js index d2877f75..4f6aed71 100644 --- a/tests/containers/containers.test.js +++ b/tests/containers/containers.test.js @@ -3,7 +3,6 @@ const Docker = require("dockerode"); const fs = require("fs"); const path = require("path"); -const tar = require("tar-fs"); const { afterAll, beforeAll, describe, it, expect } = require("@jest/globals"); @@ -113,9 +112,7 @@ describe("Service Lifecyle Integration Test", () => { await docker.checkAuth(registryAuth); - const tarStream = tar.pack(path.join(tmpDir, "my-container")); - - await docker.buildImage(tarStream, { + await docker.buildImage({context: path.join(tmpDir, "my-container"), src: ["Dockerfile", "server.py", "requirements.txt"]}, { t: imageName, registryconfig: registryAuth, }); From 55c8227571e6e3799cd6bee1592af788052a5695 Mon Sep 17 00:00:00 2001 From: norbjd Date: Fri, 27 Jun 2025 15:51:46 +0200 Subject: [PATCH 2/2] Run prettier --- deploy/lib/buildAndPushContainers.js | 60 +++++++++++++++------------- tests/containers/containers.test.js | 14 +++++-- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/deploy/lib/buildAndPushContainers.js b/deploy/lib/buildAndPushContainers.js index c4076c06..a3dd1f63 100644 --- a/deploy/lib/buildAndPushContainers.js +++ b/deploy/lib/buildAndPushContainers.js @@ -1,8 +1,8 @@ "use strict"; const Docker = require("dockerode"); -const path = require('path'); -const fs = require('fs'); +const path = require("path"); +const fs = require("fs"); const docker = new Docker(); @@ -46,30 +46,31 @@ function findErrorInBuildOutput(buildOutput) { } function getFilesInBuildContextDirectory(directory) { - let files = []; + let files = []; - try { - const dirents = fs.readdirSync(directory, { withFileTypes: true }); - - dirents.forEach(dirent => { - const absolutePath = path.join(directory, dirent.name); - if (dirent.isDirectory()) { - const subFiles = getFilesInBuildContextDirectory(absolutePath); - - // Prepend the current directory name to each subfile path - const relativeSubFiles = subFiles.map(subFile => path.join(dirent.name, subFile)); - files = files.concat(relativeSubFiles); - } else if (dirent.isFile() && dirent.name !== '.dockerignore') { - // Don't include .dockerignore file in result - files.push(dirent.name); - } - } - ); - } catch (err) { - console.error(`Error reading directory ${directory}:`, err); - } + try { + const dirents = fs.readdirSync(directory, { withFileTypes: true }); + + dirents.forEach((dirent) => { + const absolutePath = path.join(directory, dirent.name); + if (dirent.isDirectory()) { + const subFiles = getFilesInBuildContextDirectory(absolutePath); - return files; + // Prepend the current directory name to each subfile path + const relativeSubFiles = subFiles.map((subFile) => + path.join(dirent.name, subFile) + ); + files = files.concat(relativeSubFiles); + } else if (dirent.isFile() && dirent.name !== ".dockerignore") { + // Don't include .dockerignore file in result + files.push(dirent.name); + } + }); + } catch (err) { + console.error(`Error reading directory ${directory}:`, err); + } + + return files; } module.exports = { @@ -109,10 +110,13 @@ module.exports = { return new Promise(async (resolve, reject) => { let files = getFilesInBuildContextDirectory(container.directory); - const buildStream = await docker.buildImage({context: container.directory, src: files}, { - t: imageName, - registryconfig: registryAuth, - }); + const buildStream = await docker.buildImage( + { context: container.directory, src: files }, + { + t: imageName, + registryconfig: registryAuth, + } + ); const buildStreamEvents = await extractStreamContents( buildStream, this.provider.options.verbose diff --git a/tests/containers/containers.test.js b/tests/containers/containers.test.js index 4f6aed71..13ee7e55 100644 --- a/tests/containers/containers.test.js +++ b/tests/containers/containers.test.js @@ -112,10 +112,16 @@ describe("Service Lifecyle Integration Test", () => { await docker.checkAuth(registryAuth); - await docker.buildImage({context: path.join(tmpDir, "my-container"), src: ["Dockerfile", "server.py", "requirements.txt"]}, { - t: imageName, - registryconfig: registryAuth, - }); + await docker.buildImage( + { + context: path.join(tmpDir, "my-container"), + src: ["Dockerfile", "server.py", "requirements.txt"], + }, + { + t: imageName, + registryconfig: registryAuth, + } + ); const image = docker.getImage(imageName); await image.push(auth);