containerify 3.1.2 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -36
- package/lib/appLayerCreator.js +6 -6
- package/lib/cli.js +57 -81
- package/lib/dockerExporter.js +1 -1
- package/lib/logger.js +0 -1
- package/lib/registry.js +3 -2
- package/lib/types.d.ts +1 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +20 -17
package/README.md
CHANGED
|
@@ -53,42 +53,41 @@ This will take the `nginx:alpine` image, and copy the files from `./dist/` into
|
|
|
53
53
|
Usage: containerify [options]
|
|
54
54
|
|
|
55
55
|
Options:
|
|
56
|
-
--from <registry/image:tag>
|
|
57
|
-
--to <registry/image:tag>
|
|
58
|
-
--fromImage <name:tag>
|
|
59
|
-
--toImage <name:tag>
|
|
60
|
-
--folder <full path>
|
|
61
|
-
--file <path>
|
|
62
|
-
--doCrossMount
|
|
63
|
-
--fromRegistry <registry url>
|
|
64
|
-
--fromToken <token>
|
|
65
|
-
--toRegistry <registry url>
|
|
66
|
-
--optimisticToRegistryCheck
|
|
67
|
-
--toToken <token>
|
|
68
|
-
--toTar <path>
|
|
69
|
-
--toDocker
|
|
70
|
-
--registry <path>
|
|
71
|
-
--platform <platform>
|
|
72
|
-
--token <path>
|
|
73
|
-
--user <user>
|
|
74
|
-
--workdir <directory>
|
|
75
|
-
--entrypoint <entrypoint>
|
|
76
|
-
--labels <labels
|
|
77
|
-
--
|
|
78
|
-
--
|
|
79
|
-
--
|
|
80
|
-
--
|
|
81
|
-
--
|
|
82
|
-
--
|
|
83
|
-
--
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
--
|
|
87
|
-
--
|
|
88
|
-
--
|
|
89
|
-
--
|
|
90
|
-
--
|
|
91
|
-
-h, --help display help for command
|
|
56
|
+
--from <registry/image:tag> Optional: Shorthand to specify fromRegistry and fromImage in one argument
|
|
57
|
+
--to <registry/image:tag> Optional: Shorthand to specify toRegistry and toImage in one argument
|
|
58
|
+
--fromImage <name:tag> Required: Image name of base image - [path/]image:tag
|
|
59
|
+
--toImage <name:tag> Required: Image name of target image - [path/]image:tag
|
|
60
|
+
--folder <full path> Required: Base folder of node application (contains package.json)
|
|
61
|
+
--file <path> Optional: Name of configuration file (defaults to containerify.json if found on path)
|
|
62
|
+
--doCrossMount Optional: Cross mount image layers from the base image (only works if fromImage and toImage are in the same registry) (default: false)
|
|
63
|
+
--fromRegistry <registry url> Optional: URL of registry to pull base image from - Default: https://registry-1.docker.io/v2/
|
|
64
|
+
--fromToken <token> Optional: Authentication token for from registry
|
|
65
|
+
--toRegistry <registry url> Optional: URL of registry to push base image to - Default: https://registry-1.docker.io/v2/
|
|
66
|
+
--optimisticToRegistryCheck Treat redirects as layer existing in remote registry. Potentially unsafe, but can save bandwidth.
|
|
67
|
+
--toToken <token> Optional: Authentication token for target registry
|
|
68
|
+
--toTar <path> Optional: Export to tar file
|
|
69
|
+
--toDocker Optional: Export to local docker registry
|
|
70
|
+
--registry <path> Optional: Convenience argument for setting both from and to registry
|
|
71
|
+
--platform <platform> Optional: Preferred platform, e.g. linux/amd64 or arm64
|
|
72
|
+
--token <path> Optional: Convenience argument for setting token for both from and to registry
|
|
73
|
+
--user <user> Optional: User account to run process in container - default: 1000 (empty for customContent)
|
|
74
|
+
--workdir <directory> Optional: Workdir where node app will be added and run from - default: /app (empty for customContent)
|
|
75
|
+
--entrypoint <entrypoint> Optional: Entrypoint when starting container - default: npm start (empty for customContent)
|
|
76
|
+
--label, --labels <labels...> Optional: Comma-separated list of key value pairs to use as labels
|
|
77
|
+
--env, --envs <envs...> Optional: Comma-separated list of key value pairs to use av environment variables.
|
|
78
|
+
--setTimeStamp <timestamp> Optional: Set a specific ISO 8601 timestamp on all entries (e.g. git commit hash). Default: 1970 in tar files, and current time on manifest/config
|
|
79
|
+
--preserveTimeStamp Optional: Preserve timestamps on files in the added layers. This might help with cache invalidation.
|
|
80
|
+
--verbose Verbose logging
|
|
81
|
+
--allowInsecureRegistries Allow insecure registries (with self-signed/untrusted cert)
|
|
82
|
+
--allowNoPushAuth Allow pushing images without authentication/token if the registry allows it
|
|
83
|
+
--customContent <dirs/files...> Optional: Skip normal node_modules and applayer and include specified root folder files/directories instead. You can specify as
|
|
84
|
+
local-path:absolute-container-path if you want to place it in a specific location
|
|
85
|
+
--extraContent <dirs/files...> Optional: Add specific content. Specify as local-path:absolute-container-path,local-path2:absolute-container-path2 etc
|
|
86
|
+
--layerOwner <gid:uid> Optional: Set specific gid and uid on files in the added layers
|
|
87
|
+
--buildFolder <path> Optional: Use a specific build folder when creating the image
|
|
88
|
+
--layerCacheFolder <path> Optional: Folder to cache base layers between builds
|
|
89
|
+
--version Get containerify version
|
|
90
|
+
-h, --help display help for command
|
|
92
91
|
```
|
|
93
92
|
|
|
94
93
|
## Detailed info
|
package/lib/appLayerCreator.js
CHANGED
|
@@ -75,10 +75,10 @@ function calculateHash(path) {
|
|
|
75
75
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
function copySync(src, dest) {
|
|
79
|
-
const copyOptions = { overwrite: true, dereference: true };
|
|
78
|
+
function copySync(src, dest, preserveTimestamps) {
|
|
79
|
+
const copyOptions = { overwrite: true, dereference: true, preserveTimestamps: preserveTimestamps };
|
|
80
80
|
const destFolder = dest.substring(0, dest.lastIndexOf("/"));
|
|
81
|
-
logger_1.default.debug(
|
|
81
|
+
logger_1.default.debug(`Copying ${src} to ${dest}`);
|
|
82
82
|
fse.ensureDirSync(destFolder);
|
|
83
83
|
fse.copySync(src, dest, copyOptions);
|
|
84
84
|
}
|
|
@@ -112,10 +112,10 @@ function addDataLayer(tmpdir, todir, options, config, manifest, files, comment)
|
|
|
112
112
|
const buildDir = yield fileutil.ensureEmptyDir(path.join(tmpdir, "build"));
|
|
113
113
|
files.map((f) => {
|
|
114
114
|
if (Array.isArray(f)) {
|
|
115
|
-
copySync(path.join(options.folder, f[0]), path.join(buildDir, f[1]));
|
|
115
|
+
copySync(path.join(options.folder, f[0]), path.join(buildDir, f[1]), !!options.preserveTimeStamp);
|
|
116
116
|
}
|
|
117
117
|
else {
|
|
118
|
-
copySync(path.join(options.folder, f), path.join(buildDir, options.workdir, f));
|
|
118
|
+
copySync(path.join(options.folder, f), path.join(buildDir, options.workdir, f), !!options.preserveTimeStamp);
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
121
|
const layerFile = path.join(todir, "layer.tar.gz");
|
|
@@ -127,7 +127,7 @@ function addDataLayer(tmpdir, todir, options, config, manifest, files, comment)
|
|
|
127
127
|
comment +
|
|
128
128
|
(comment == "dependencies" ? ". Did you forget to run npm install?" : ""));
|
|
129
129
|
}
|
|
130
|
-
yield tar.create(Object.assign(Object.assign({}, tarDefaultConfig), Object.assign({ statCache: statCache(options.layerOwner), portable: !options.layerOwner, prefix: "/", cwd: buildDir, file: layerFile, gzip: true, noMtime: !options.setTimeStamp }, (options.setTimeStamp ? { mtime: new Date(options.setTimeStamp) } : {}))), filesToTar);
|
|
130
|
+
yield tar.create(Object.assign(Object.assign({}, tarDefaultConfig), Object.assign({ statCache: statCache(options.layerOwner), portable: !options.layerOwner, prefix: "/", cwd: buildDir, file: layerFile, gzip: true, noMtime: !(options.setTimeStamp || options.preserveTimeStamp) }, (options.setTimeStamp ? { mtime: new Date(options.setTimeStamp) } : {}))), filesToTar);
|
|
131
131
|
const fhash = yield calculateHash(layerFile);
|
|
132
132
|
const finalName = path.join(todir, fhash + ".tar.gz");
|
|
133
133
|
yield fse.move(layerFile, finalName);
|
package/lib/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
10
|
});
|
|
11
11
|
};
|
|
12
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
12
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
const os = require("os");
|
|
15
15
|
const commander_1 = require("commander");
|
|
@@ -25,67 +25,51 @@ const types_1 = require("./types");
|
|
|
25
25
|
const utils_1 = require("./utils");
|
|
26
26
|
const fileutil_1 = require("./fileutil");
|
|
27
27
|
const version_1 = require("./version");
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"--
|
|
33
|
-
"--
|
|
34
|
-
"--
|
|
35
|
-
"--
|
|
36
|
-
"--
|
|
37
|
-
"--
|
|
38
|
-
"--
|
|
39
|
-
"--
|
|
40
|
-
"--
|
|
41
|
-
"--
|
|
42
|
-
"--
|
|
43
|
-
"--
|
|
44
|
-
"--
|
|
45
|
-
"--
|
|
46
|
-
"--
|
|
47
|
-
"--
|
|
48
|
-
"--
|
|
49
|
-
"--
|
|
50
|
-
"--
|
|
51
|
-
"--
|
|
52
|
-
"--
|
|
53
|
-
"--
|
|
54
|
-
"--
|
|
55
|
-
"--
|
|
56
|
-
"--
|
|
57
|
-
"--
|
|
58
|
-
"--
|
|
59
|
-
"--
|
|
60
|
-
"--
|
|
61
|
-
"--
|
|
62
|
-
"--
|
|
63
|
-
|
|
28
|
+
const program = new commander_1.Command();
|
|
29
|
+
program
|
|
30
|
+
.name("containerify")
|
|
31
|
+
.description("A CLI-tool for creating container images.")
|
|
32
|
+
.option("--from <registry/image:tag>", "Optional: Shorthand to specify fromRegistry and fromImage in one argument")
|
|
33
|
+
.option("--to <registry/image:tag>", "Optional: Shorthand to specify toRegistry and toImage in one argument")
|
|
34
|
+
.option("--fromImage <name:tag>", "Required: Image name of base image - [path/]image:tag")
|
|
35
|
+
.option("--toImage <name:tag>", "Required: Image name of target image - [path/]image:tag")
|
|
36
|
+
.option("--folder <full path>", "Required: Base folder of node application (contains package.json)")
|
|
37
|
+
.option("--file <path>", "Optional: Name of configuration file (defaults to containerify.json if found on path)")
|
|
38
|
+
.option("--doCrossMount", "Optional: Cross mount image layers from the base image (only works if fromImage and toImage are in the same registry) (default, false)")
|
|
39
|
+
.option("--fromRegistry <registry url>", "Optional: URL of registry to pull base image from - Default, https,//registry-1.docker.io/v2/")
|
|
40
|
+
.option("--fromToken <token>", "Optional: Authentication token for from registry")
|
|
41
|
+
.option("--toRegistry <registry url>", "Optional: URL of registry to push base image to - Default, https,//registry-1.docker.io/v2/")
|
|
42
|
+
.option("--optimisticToRegistryCheck", "Treat redirects as layer existing in remote registry. Potentially unsafe) but can save bandwidth.")
|
|
43
|
+
.option("--toToken <token>", "Optional: Authentication token for target registry")
|
|
44
|
+
.option("--toTar <path>", "Optional: Export to tar file")
|
|
45
|
+
.option("--toDocker", "Optional: Export to local docker registry")
|
|
46
|
+
.option("--registry <path>", "Optional: Convenience argument for setting both from and to registry")
|
|
47
|
+
.option("--platform <platform>", "Optional: Preferred platform) e.g. linux/amd64 or arm64")
|
|
48
|
+
.option("--token <path>", "Optional: Convenience argument for setting token for both from and to registry")
|
|
49
|
+
.option("--user <user>", "Optional: User account to run process in container - default, 1000 (empty for customContent)")
|
|
50
|
+
.option("--workdir <directory>", "Optional: Workdir where node app will be added and run from - default, /app (empty for customContent)")
|
|
51
|
+
.option("--entrypoint <entrypoint>", "Optional: Entrypoint when starting container - default, npm start (empty for customContent)")
|
|
52
|
+
.option("--label, --labels <labels...>", "Optional: Comma-separated list of key value pairs to use as labels")
|
|
53
|
+
.option("--env, --envs <envs...>", "Optional: Comma-separated list of key value pairs to use av environment variables.")
|
|
54
|
+
.option("--preserveTimeStamp", "Optional: Preserve timestamps on files in the added layers. This might help with cache invalidation.")
|
|
55
|
+
.option("--setTimeStamp <timestamp>", "Optional: Set a specific ISO 8601 timestamp on all entries (e.g. git commit hash). Default, 1970 in tar files) and current time on manifest/config")
|
|
56
|
+
.option("--verbose", "Verbose logging")
|
|
57
|
+
.option("--allowInsecureRegistries", "Allow insecure registries (with self-signed/untrusted cert)")
|
|
58
|
+
.option("--allowNoPushAuth", "Allow pushing images without a authentication/token to registries that allow it")
|
|
59
|
+
.option("--customContent <dirs/files...>", "Optional: Skip normal node_modules and applayer and include specified root folder files/directories instead. You can specify as local-path,absolute-container-path if you want to place it in a specific location")
|
|
60
|
+
.option("--extraContent <dirs/files...>", "Optional: Add specific content. Specify as local-path,absolute-container-path)local-path2,absolute-container-path2 etc")
|
|
61
|
+
.option("--layerOwner <gid:uid>", "Optional: Set specific gid and uid on files in the added layers")
|
|
62
|
+
.option("--buildFolder <path>", "Optional: Use a specific build folder when creating the image")
|
|
63
|
+
.option("--layerCacheFolder <path>", "Optional: Folder to cache base layers between builds")
|
|
64
|
+
.version(version_1.VERSION, "--version", "Get containerify version");
|
|
65
|
+
program.parse(process.argv);
|
|
64
66
|
function setKeyValue(target, keyValue, separator = "=", defaultValue) {
|
|
65
67
|
var _a;
|
|
66
68
|
const [k, v] = keyValue.split(separator, 2);
|
|
67
69
|
target[k.trim()] = (_a = v === null || v === void 0 ? void 0 : v.trim()) !== null && _a !== void 0 ? _a : defaultValue;
|
|
68
70
|
}
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
setKeyValue(cliLabels, ops);
|
|
72
|
-
});
|
|
73
|
-
const cliEnv = {};
|
|
74
|
-
commander_1.program.on("option:env", (ops) => {
|
|
75
|
-
setKeyValue(cliEnv, ops);
|
|
76
|
-
});
|
|
77
|
-
const cliOptions = Object.entries(possibleArgs)
|
|
78
|
-
.reduce((program, [k, v]) => {
|
|
79
|
-
program.option(k, v);
|
|
80
|
-
return program;
|
|
81
|
-
}, commander_1.program)
|
|
82
|
-
.parse()
|
|
83
|
-
.opts();
|
|
84
|
-
if (cliOptions.version) {
|
|
85
|
-
console.log(`containerify v${version_1.VERSION}`);
|
|
86
|
-
process.exit(0);
|
|
87
|
-
}
|
|
88
|
-
const keys = Object.keys(possibleArgs).map((k) => k.split(" ")[0].replace("--", ""));
|
|
71
|
+
const cliOptions = program.opts();
|
|
72
|
+
const keys = program.options.map((x) => { var _a; return (_a = x.long) === null || _a === void 0 ? void 0 : _a.replace("--", ""); });
|
|
89
73
|
const defaultOptions = {
|
|
90
74
|
workdir: "/app",
|
|
91
75
|
user: "1000",
|
|
@@ -107,26 +91,17 @@ Object.keys(configFromFile).forEach((k) => {
|
|
|
107
91
|
}
|
|
108
92
|
});
|
|
109
93
|
const labelsOpt = {};
|
|
110
|
-
(
|
|
111
|
-
Object.
|
|
112
|
-
.filter((l) => Object.keys(cliLabels).includes(l))
|
|
113
|
-
.forEach((l) => {
|
|
114
|
-
exitWithErrorIf(true, `Label ${l} specified both with --labels and --label`);
|
|
115
|
-
});
|
|
116
|
-
const labels = Object.assign(Object.assign(Object.assign({}, configFromFile.labels), labelsOpt), cliLabels); //Let cli arguments override file
|
|
94
|
+
(_a = cliOptions.labels) === null || _a === void 0 ? void 0 : _a.forEach((labels) => labels.split(",").forEach((label) => setKeyValue(labelsOpt, label)));
|
|
95
|
+
const labels = Object.assign(Object.assign({}, configFromFile.labels), labelsOpt); //Let cli arguments override file
|
|
117
96
|
const envOpt = {};
|
|
118
|
-
(
|
|
119
|
-
Object.
|
|
120
|
-
|
|
121
|
-
.forEach((l) => {
|
|
122
|
-
exitWithErrorIf(true, `Env ${l} specified both with --envs and --env`);
|
|
123
|
-
});
|
|
124
|
-
const envs = Object.assign(Object.assign(Object.assign({}, configFromFile.envs), envOpt), cliEnv); //Let cli arguments override file
|
|
97
|
+
(_b = cliOptions.envs) === null || _b === void 0 ? void 0 : _b.forEach((envs) => envs.split(",").forEach((env) => setKeyValue(envOpt, env)));
|
|
98
|
+
const envs = Object.assign(Object.assign({}, configFromFile.envs), envOpt); //Let cli arguments override file
|
|
99
|
+
console.log(envs);
|
|
125
100
|
const customContent = {};
|
|
126
|
-
(
|
|
127
|
-
(
|
|
101
|
+
(_c = configFromFile.customContent) === null || _c === void 0 ? void 0 : _c.forEach((c) => setKeyValue(customContent, c, ":", c));
|
|
102
|
+
(_d = cliOptions.customContent) === null || _d === void 0 ? void 0 : _d.forEach((contents) => contents.split(",").forEach((content) => setKeyValue(customContent, content, ":", content)));
|
|
128
103
|
const cliExtraContent = {};
|
|
129
|
-
(
|
|
104
|
+
(_e = cliOptions.extraContent) === null || _e === void 0 ? void 0 : _e.forEach((extras) => extras.split(",").forEach((extra) => setKeyValue(cliExtraContent, extra, ":")));
|
|
130
105
|
const extraContent = Object.assign(Object.assign({}, configFromFile.extraContent), cliExtraContent);
|
|
131
106
|
const cliParams = (0, utils_1.omit)(cliOptions, [
|
|
132
107
|
"label",
|
|
@@ -147,11 +122,12 @@ const options = Object.assign(Object.assign(Object.assign({}, defaultOptions), s
|
|
|
147
122
|
function exitWithErrorIf(check, error) {
|
|
148
123
|
if (check) {
|
|
149
124
|
logger_1.default.error("ERROR: " + error);
|
|
150
|
-
|
|
125
|
+
program.help({ error: true });
|
|
151
126
|
}
|
|
152
127
|
}
|
|
153
128
|
if (options.verbose)
|
|
154
129
|
logger_1.default.enableDebug();
|
|
130
|
+
exitWithErrorIf(!!options.setTimeStamp && !!options.preserveTimeStamp, "Do not set both --preserveTimeStamp and --setTimeStamp");
|
|
155
131
|
exitWithErrorIf(!!options.registry && !!options.fromRegistry, "Do not set both --registry and --fromRegistry");
|
|
156
132
|
exitWithErrorIf(!!options.from && !!options.fromRegistry, "Do not set both --from and --fromRegistry");
|
|
157
133
|
exitWithErrorIf(!!options.registry && !!options.from, "Do not set both --registry and --from");
|
|
@@ -202,11 +178,11 @@ if (options.toRegistry && !options.toRegistry.endsWith("/"))
|
|
|
202
178
|
options.toRegistry += "/";
|
|
203
179
|
if (options.fromRegistry && !options.fromRegistry.endsWith("/"))
|
|
204
180
|
options.fromRegistry += "/";
|
|
205
|
-
if (!options.fromRegistry && !((
|
|
181
|
+
if (!options.fromRegistry && !((_h = (_g = (_f = options.fromImage) === null || _f === void 0 ? void 0 : _f.split(":")) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.includes("/"))) {
|
|
206
182
|
options.fromImage = "library/" + options.fromImage;
|
|
207
183
|
}
|
|
208
184
|
Object.keys(options.customContent).forEach((p) => {
|
|
209
|
-
exitWithErrorIf(!fs.existsSync(p),
|
|
185
|
+
exitWithErrorIf(!fs.existsSync(p), `Could not find ${p} in the base folder ${options.folder}`);
|
|
210
186
|
});
|
|
211
187
|
if (options.layerCacheFolder) {
|
|
212
188
|
if (!fs.existsSync(options.layerCacheFolder)) {
|
|
@@ -215,7 +191,7 @@ if (options.layerCacheFolder) {
|
|
|
215
191
|
fs.mkdirSync(options.layerCacheFolder, { recursive: true });
|
|
216
192
|
}
|
|
217
193
|
catch (e) {
|
|
218
|
-
exitWithErrorIf(true,
|
|
194
|
+
exitWithErrorIf(true, `Failed to create layer cache folder ${e}`);
|
|
219
195
|
}
|
|
220
196
|
}
|
|
221
197
|
if (!options.layerCacheFolder.endsWith("/")) {
|
|
@@ -223,13 +199,13 @@ if (options.layerCacheFolder) {
|
|
|
223
199
|
}
|
|
224
200
|
}
|
|
225
201
|
Object.keys(options.extraContent).forEach((k) => {
|
|
226
|
-
exitWithErrorIf(!fs.existsSync(options.folder + k),
|
|
202
|
+
exitWithErrorIf(!fs.existsSync(options.folder + k), `Could not find '${k}' in the folder ${options.folder}`);
|
|
227
203
|
});
|
|
228
204
|
function run(options) {
|
|
229
205
|
return __awaiter(this, void 0, void 0, function* () {
|
|
230
206
|
var _a;
|
|
231
207
|
if (!(yield fse.pathExists(options.folder)))
|
|
232
|
-
throw new Error(
|
|
208
|
+
throw new Error(`No such folder: ${options.folder}`);
|
|
233
209
|
const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), "containerify-"));
|
|
234
210
|
logger_1.default.debug("Using " + tmpdir);
|
|
235
211
|
const fromdir = yield (0, fileutil_1.ensureEmptyDir)(path.join(tmpdir, "from"));
|
|
@@ -254,7 +230,7 @@ function run(options) {
|
|
|
254
230
|
const toRegistry = yield (0, registry_1.createRegistry)(options.toRegistry, options.toImage, allowInsecure, options.toToken, options.optimisticToRegistryCheck);
|
|
255
231
|
yield toRegistry.upload(options.toImage, todir, options.doCrossMount, originalManifest, options.fromImage);
|
|
256
232
|
}
|
|
257
|
-
logger_1.default.debug(
|
|
233
|
+
logger_1.default.debug(`Deleting ${tmpdir} ...`);
|
|
258
234
|
yield fse.remove(tmpdir);
|
|
259
235
|
logger_1.default.debug("Done");
|
|
260
236
|
});
|
package/lib/dockerExporter.js
CHANGED
package/lib/logger.js
CHANGED
package/lib/registry.js
CHANGED
|
@@ -130,7 +130,7 @@ function uploadContent(uploadUrl, file, fileConfig, allowInsecure, auth, content
|
|
|
130
130
|
}
|
|
131
131
|
function processToken(registryBaseUrl, allowInsecure, imagePath, token) {
|
|
132
132
|
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
-
const { hostname } = URL.
|
|
133
|
+
const { hostname } = new URL.URL(registryBaseUrl);
|
|
134
134
|
const image = (0, utils_1.parseImage)(imagePath);
|
|
135
135
|
if ((hostname === null || hostname === void 0 ? void 0 : hostname.endsWith(".docker.io")) && !token)
|
|
136
136
|
return getDockerToken(image.path, allowInsecure);
|
|
@@ -140,7 +140,8 @@ function processToken(registryBaseUrl, allowInsecure, imagePath, token) {
|
|
|
140
140
|
return getGitLabToken(token, image.path, allowInsecure);
|
|
141
141
|
if (token.startsWith("Basic "))
|
|
142
142
|
return token;
|
|
143
|
-
|
|
143
|
+
const githubPrefixes = ["ghp_", "github_pat_", "gho_", "ghu_", "ghs_"];
|
|
144
|
+
if (githubPrefixes.some((prefix) => token.startsWith(prefix)))
|
|
144
145
|
return "Bearer " + Buffer.from(token).toString("base64");
|
|
145
146
|
return "Bearer " + token;
|
|
146
147
|
});
|
package/lib/types.d.ts
CHANGED
package/lib/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "3.1
|
|
1
|
+
export declare const VERSION = "3.2.1";
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "containerify",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "Build node.js docker images without docker",
|
|
5
5
|
"main": "./lib/cli.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prebuild": "node -p \"'export const VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > src/version.ts",
|
|
8
8
|
"build": "tsc && chmod ugo+x lib/cli.js",
|
|
9
|
-
"lint": "eslint . --ext .ts --fix
|
|
9
|
+
"lint": "eslint . --ext .ts --fix",
|
|
10
10
|
"typecheck": "tsc --noEmit",
|
|
11
11
|
"watch": "tsc --watch",
|
|
12
12
|
"check": "npm run lint && npm run typecheck",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"allTests": "npm run integrationTest && npm run registryTest"
|
|
17
17
|
},
|
|
18
18
|
"bin": {
|
|
19
|
-
"containerify": "
|
|
19
|
+
"containerify": "lib/cli.js"
|
|
20
20
|
},
|
|
21
21
|
"author": "Erlend Oftedal <erlend@oftedal.no>",
|
|
22
22
|
"contributors": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/eoftedal/containerify.git"
|
|
28
|
+
"url": "git+https://github.com/eoftedal/containerify.git"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"lib/"
|
|
@@ -36,20 +36,23 @@
|
|
|
36
36
|
"image"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"commander": "^
|
|
40
|
-
"fs-extra": "^11.
|
|
41
|
-
"tar": "^6.1
|
|
39
|
+
"commander": "^13.1.0",
|
|
40
|
+
"fs-extra": "^11.3.0",
|
|
41
|
+
"tar": "^6.2.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@
|
|
45
|
-
"@
|
|
46
|
-
"@types/
|
|
47
|
-
"@types/
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
50
|
-
"eslint": "^8.
|
|
51
|
-
"eslint
|
|
52
|
-
"
|
|
53
|
-
"
|
|
44
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
45
|
+
"@eslint/js": "^9.23.0",
|
|
46
|
+
"@types/fs-extra": "^11.0.4",
|
|
47
|
+
"@types/minizlib": "^2.1.7",
|
|
48
|
+
"@types/node": "^22.13.9",
|
|
49
|
+
"@types/tar": "^6.1.13",
|
|
50
|
+
"@typescript-eslint/eslint-plugin": "^8.26.0",
|
|
51
|
+
"@typescript-eslint/parser": "^8.26",
|
|
52
|
+
"eslint": "^9.21.0",
|
|
53
|
+
"eslint-config-prettier": "^10.1.1",
|
|
54
|
+
"globals": "^16.0.0",
|
|
55
|
+
"prettier": "^3.5.3",
|
|
56
|
+
"typescript": "^5.8.2"
|
|
54
57
|
}
|
|
55
58
|
}
|