kamal 2.3.0 → 2.5.0
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.
- checksums.yaml +4 -4
- data/lib/kamal/cli/accessory.rb +24 -9
- data/lib/kamal/cli/alias/command.rb +1 -0
- data/lib/kamal/cli/app/boot.rb +2 -2
- data/lib/kamal/cli/app.rb +28 -8
- data/lib/kamal/cli/base.rb +16 -1
- data/lib/kamal/cli/build.rb +36 -14
- data/lib/kamal/cli/main.rb +4 -3
- data/lib/kamal/cli/proxy.rb +2 -4
- data/lib/kamal/cli/registry.rb +2 -0
- data/lib/kamal/cli/secrets.rb +9 -3
- data/lib/kamal/cli/templates/deploy.yml +6 -3
- data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
- data/lib/kamal/cli.rb +1 -0
- data/lib/kamal/commander.rb +16 -25
- data/lib/kamal/commands/accessory/proxy.rb +16 -0
- data/lib/kamal/commands/accessory.rb +4 -4
- data/lib/kamal/commands/app/assets.rb +4 -4
- data/lib/kamal/commands/app/containers.rb +2 -2
- data/lib/kamal/commands/app/execution.rb +4 -2
- data/lib/kamal/commands/app/images.rb +1 -1
- data/lib/kamal/commands/app/logging.rb +14 -4
- data/lib/kamal/commands/app.rb +15 -7
- data/lib/kamal/commands/base.rb +25 -1
- data/lib/kamal/commands/builder/base.rb +17 -6
- data/lib/kamal/commands/builder/cloud.rb +22 -0
- data/lib/kamal/commands/builder.rb +6 -20
- data/lib/kamal/commands/registry.rb +9 -7
- data/lib/kamal/configuration/accessory.rb +41 -9
- data/lib/kamal/configuration/builder.rb +8 -0
- data/lib/kamal/configuration/docs/accessory.yml +26 -3
- data/lib/kamal/configuration/docs/alias.yml +2 -2
- data/lib/kamal/configuration/docs/builder.yml +9 -0
- data/lib/kamal/configuration/docs/proxy.yml +13 -10
- data/lib/kamal/configuration/docs/registry.yml +4 -0
- data/lib/kamal/configuration/registry.rb +6 -6
- data/lib/kamal/configuration/role.rb +6 -6
- data/lib/kamal/configuration/validator/role.rb +1 -1
- data/lib/kamal/configuration.rb +31 -14
- data/lib/kamal/docker.rb +30 -0
- data/lib/kamal/git.rb +10 -0
- data/lib/kamal/secrets/adapters/aws_secrets_manager.rb +50 -0
- data/lib/kamal/secrets/adapters/base.rb +13 -3
- data/lib/kamal/secrets/adapters/bitwarden.rb +2 -2
- data/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb +72 -0
- data/lib/kamal/secrets/adapters/doppler.rb +57 -0
- data/lib/kamal/secrets/adapters/enpass.rb +71 -0
- data/lib/kamal/secrets/adapters/gcp_secret_manager.rb +112 -0
- data/lib/kamal/secrets/adapters/last_pass.rb +3 -2
- data/lib/kamal/secrets/adapters/one_password.rb +2 -2
- data/lib/kamal/secrets/adapters/test.rb +2 -2
- data/lib/kamal/secrets/adapters.rb +2 -0
- data/lib/kamal/secrets.rb +1 -1
- data/lib/kamal/version.rb +1 -1
- metadata +13 -3
@@ -4,10 +4,10 @@ module Kamal::Commands::App::Assets
|
|
4
4
|
|
5
5
|
combine \
|
6
6
|
make_directory(role.asset_extracted_directory),
|
7
|
-
[ *docker(:
|
8
|
-
docker(:
|
9
|
-
docker(:cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_directory),
|
10
|
-
docker(:
|
7
|
+
[ *docker(:container, :rm, asset_container, "2> /dev/null"), "|| true" ],
|
8
|
+
docker(:container, :create, "--name", asset_container, config.absolute_image),
|
9
|
+
docker(:container, :cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_directory),
|
10
|
+
docker(:container, :rm, asset_container),
|
11
11
|
by: "&&"
|
12
12
|
end
|
13
13
|
|
@@ -2,7 +2,7 @@ module Kamal::Commands::App::Containers
|
|
2
2
|
DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'"
|
3
3
|
|
4
4
|
def list_containers
|
5
|
-
docker :container, :ls, "--all", *
|
5
|
+
docker :container, :ls, "--all", *container_filter_args
|
6
6
|
end
|
7
7
|
|
8
8
|
def list_container_names
|
@@ -20,7 +20,7 @@ module Kamal::Commands::App::Containers
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def remove_containers
|
23
|
-
docker :container, :prune, "--force", *
|
23
|
+
docker :container, :prune, "--force", *container_filter_args
|
24
24
|
end
|
25
25
|
|
26
26
|
def container_health_log(version:)
|
@@ -7,13 +7,15 @@ module Kamal::Commands::App::Execution
|
|
7
7
|
*command
|
8
8
|
end
|
9
9
|
|
10
|
-
def execute_in_new_container(*command, interactive: false, env:)
|
10
|
+
def execute_in_new_container(*command, interactive: false, detach: false, env:)
|
11
11
|
docker :run,
|
12
12
|
("-it" if interactive),
|
13
|
-
"--
|
13
|
+
("--detach" if detach),
|
14
|
+
("--rm" unless detach),
|
14
15
|
"--network", "kamal",
|
15
16
|
*role&.env_args(host),
|
16
17
|
*argumentize("--env", env),
|
18
|
+
*role.logging_args,
|
17
19
|
*config.volume_args,
|
18
20
|
*role&.option_args,
|
19
21
|
config.absolute_image,
|
@@ -1,18 +1,28 @@
|
|
1
1
|
module Kamal::Commands::App::Logging
|
2
|
-
def logs(
|
2
|
+
def logs(container_id: nil, timestamps: true, since: nil, lines: nil, grep: nil, grep_options: nil)
|
3
3
|
pipe \
|
4
|
-
|
4
|
+
container_id_command(container_id),
|
5
5
|
"xargs docker logs#{" --timestamps" if timestamps}#{" --since #{since}" if since}#{" --tail #{lines}" if lines} 2>&1",
|
6
6
|
("grep '#{grep}'#{" #{grep_options}" if grep_options}" if grep)
|
7
7
|
end
|
8
8
|
|
9
|
-
def follow_logs(host:, timestamps: true, lines: nil, grep: nil, grep_options: nil)
|
9
|
+
def follow_logs(host:, container_id: nil, timestamps: true, lines: nil, grep: nil, grep_options: nil)
|
10
10
|
run_over_ssh \
|
11
11
|
pipe(
|
12
|
-
|
12
|
+
container_id_command(container_id),
|
13
13
|
"xargs docker logs#{" --timestamps" if timestamps}#{" --tail #{lines}" if lines} --follow 2>&1",
|
14
14
|
(%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
|
15
15
|
),
|
16
16
|
host: host
|
17
17
|
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def container_id_command(container_id)
|
22
|
+
case container_id
|
23
|
+
when Array then container_id
|
24
|
+
when String, Symbol then "echo #{container_id}"
|
25
|
+
else current_running_container_id
|
26
|
+
end
|
27
|
+
end
|
18
28
|
end
|
data/lib/kamal/commands/app.rb
CHANGED
@@ -47,7 +47,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def info
|
50
|
-
docker :ps, *
|
50
|
+
docker :ps, *container_filter_args
|
51
51
|
end
|
52
52
|
|
53
53
|
|
@@ -67,7 +67,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
67
67
|
|
68
68
|
def list_versions(*docker_args, statuses: nil)
|
69
69
|
pipe \
|
70
|
-
docker(:ps, *
|
70
|
+
docker(:ps, *container_filter_args(statuses: statuses), *docker_args, "--format", '"{{.Names}}"'),
|
71
71
|
extract_version_from_name
|
72
72
|
end
|
73
73
|
|
@@ -91,11 +91,15 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def latest_container(format:, filters: nil)
|
94
|
-
docker :ps, "--latest", *format, *
|
94
|
+
docker :ps, "--latest", *format, *container_filter_args(statuses: ACTIVE_DOCKER_STATUSES), argumentize("--filter", filters)
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
98
|
-
argumentize "--filter",
|
97
|
+
def container_filter_args(statuses: nil)
|
98
|
+
argumentize "--filter", container_filters(statuses: statuses)
|
99
|
+
end
|
100
|
+
|
101
|
+
def image_filter_args
|
102
|
+
argumentize "--filter", image_filters
|
99
103
|
end
|
100
104
|
|
101
105
|
def extract_version_from_name
|
@@ -103,13 +107,17 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
103
107
|
%(while read line; do echo ${line##{role.container_prefix}-}; done)
|
104
108
|
end
|
105
109
|
|
106
|
-
def
|
110
|
+
def container_filters(statuses: nil)
|
107
111
|
[ "label=service=#{config.service}" ].tap do |filters|
|
108
|
-
filters << "label=destination=#{config.destination}"
|
112
|
+
filters << "label=destination=#{config.destination}"
|
109
113
|
filters << "label=role=#{role}" if role
|
110
114
|
statuses&.each do |status|
|
111
115
|
filters << "status=#{status}"
|
112
116
|
end
|
113
117
|
end
|
114
118
|
end
|
119
|
+
|
120
|
+
def image_filters
|
121
|
+
[ "label=service=#{config.service}" ]
|
122
|
+
end
|
115
123
|
end
|
data/lib/kamal/commands/base.rb
CHANGED
@@ -11,7 +11,7 @@ module Kamal::Commands
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def run_over_ssh(*command, host:)
|
14
|
-
"ssh#{ssh_proxy_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\''")}'"
|
14
|
+
"ssh#{ssh_proxy_args}#{ssh_keys_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\''")}'"
|
15
15
|
end
|
16
16
|
|
17
17
|
def container_id_for(container_name:, only_running: false)
|
@@ -34,6 +34,12 @@ module Kamal::Commands
|
|
34
34
|
[ :rm, path ]
|
35
35
|
end
|
36
36
|
|
37
|
+
def ensure_docker_installed
|
38
|
+
combine \
|
39
|
+
ensure_local_docker_installed,
|
40
|
+
ensure_local_buildx_installed
|
41
|
+
end
|
42
|
+
|
37
43
|
private
|
38
44
|
def combine(*commands, by: "&&")
|
39
45
|
commands
|
@@ -94,5 +100,23 @@ module Kamal::Commands
|
|
94
100
|
" -o ProxyCommand='#{config.ssh.proxy.command_line_template}'"
|
95
101
|
end
|
96
102
|
end
|
103
|
+
|
104
|
+
def ssh_keys_args
|
105
|
+
"#{ ssh_keys.join("") if ssh_keys}" + "#{" -o IdentitiesOnly=yes" if config.ssh&.keys_only}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def ssh_keys
|
109
|
+
config.ssh.keys&.map do |key|
|
110
|
+
" -i #{key}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def ensure_local_docker_installed
|
115
|
+
docker "--version"
|
116
|
+
end
|
117
|
+
|
118
|
+
def ensure_local_buildx_installed
|
119
|
+
docker :buildx, "version"
|
120
|
+
end
|
97
121
|
end
|
98
122
|
end
|
@@ -6,18 +6,19 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
6
6
|
delegate :argumentize, to: Kamal::Utils
|
7
7
|
delegate \
|
8
8
|
:args, :secrets, :dockerfile, :target, :arches, :local_arches, :remote_arches, :remote,
|
9
|
-
:cache_from, :cache_to, :ssh, :provenance, :driver, :docker_driver?,
|
9
|
+
:cache_from, :cache_to, :ssh, :provenance, :sbom, :driver, :docker_driver?,
|
10
10
|
to: :builder_config
|
11
11
|
|
12
12
|
def clean
|
13
13
|
docker :image, :rm, "--force", config.absolute_image
|
14
14
|
end
|
15
15
|
|
16
|
-
def push
|
16
|
+
def push(export_action = "registry", tag_as_dirty: false)
|
17
17
|
docker :buildx, :build,
|
18
|
-
"--
|
18
|
+
"--output=type=#{export_action}",
|
19
19
|
*platform_options(arches),
|
20
20
|
*([ "--builder", builder_name ] unless docker_driver?),
|
21
|
+
*build_tag_options(tag_as_dirty: tag_as_dirty),
|
21
22
|
*build_options,
|
22
23
|
build_context
|
23
24
|
end
|
@@ -37,7 +38,7 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def build_options
|
40
|
-
[ *
|
41
|
+
[ *build_cache, *build_labels, *build_args, *build_secrets, *build_dockerfile, *build_target, *build_ssh, *builder_provenance, *builder_sbom ]
|
41
42
|
end
|
42
43
|
|
43
44
|
def build_context
|
@@ -58,8 +59,14 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
58
59
|
end
|
59
60
|
|
60
61
|
private
|
61
|
-
def
|
62
|
-
[
|
62
|
+
def build_tag_names(tag_as_dirty: false)
|
63
|
+
tag_names = [ config.absolute_image, config.latest_image ]
|
64
|
+
tag_names.map! { |t| "#{t}-dirty" } if tag_as_dirty
|
65
|
+
tag_names
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_tag_options(tag_as_dirty: false)
|
69
|
+
build_tag_names(tag_as_dirty: tag_as_dirty).flat_map { |name| [ "-t", name ] }
|
63
70
|
end
|
64
71
|
|
65
72
|
def build_cache
|
@@ -101,6 +108,10 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
101
108
|
argumentize "--provenance", provenance unless provenance.nil?
|
102
109
|
end
|
103
110
|
|
111
|
+
def builder_sbom
|
112
|
+
argumentize "--sbom", sbom unless sbom.nil?
|
113
|
+
end
|
114
|
+
|
104
115
|
def builder_config
|
105
116
|
config.builder
|
106
117
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Kamal::Commands::Builder::Cloud < Kamal::Commands::Builder::Base
|
2
|
+
# Expects `driver` to be of format "cloud docker-org-name/builder-name"
|
3
|
+
|
4
|
+
def create
|
5
|
+
docker :buildx, :create, "--driver", driver
|
6
|
+
end
|
7
|
+
|
8
|
+
def remove
|
9
|
+
docker :buildx, :rm, builder_name
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def builder_name
|
14
|
+
driver.gsub(/[ \/]/, "-")
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect_buildx
|
18
|
+
pipe \
|
19
|
+
docker(:buildx, :inspect, builder_name),
|
20
|
+
grep("-q", "Endpoint:.*cloud://.*")
|
21
|
+
end
|
22
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require "active_support/core_ext/string/filters"
|
2
2
|
|
3
3
|
class Kamal::Commands::Builder < Kamal::Commands::Base
|
4
|
-
delegate :create, :remove, :push, :clean, :pull, :info, :inspect_builder, :validate_image, :first_mirror, to: :target
|
5
|
-
delegate :local?, :remote?, to: "config.builder"
|
4
|
+
delegate :create, :remove, :dev, :push, :clean, :pull, :info, :inspect_builder, :validate_image, :first_mirror, to: :target
|
5
|
+
delegate :local?, :remote?, :cloud?, to: "config.builder"
|
6
6
|
|
7
7
|
include Clone
|
8
8
|
|
@@ -17,6 +17,8 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
17
17
|
else
|
18
18
|
remote
|
19
19
|
end
|
20
|
+
elsif cloud?
|
21
|
+
cloud
|
20
22
|
else
|
21
23
|
local
|
22
24
|
end
|
@@ -34,23 +36,7 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
34
36
|
@hybrid ||= Kamal::Commands::Builder::Hybrid.new(config)
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
if name.native?
|
40
|
-
ensure_local_docker_installed
|
41
|
-
else
|
42
|
-
combine \
|
43
|
-
ensure_local_docker_installed,
|
44
|
-
ensure_local_buildx_installed
|
45
|
-
end
|
39
|
+
def cloud
|
40
|
+
@cloud ||= Kamal::Commands::Builder::Cloud.new(config)
|
46
41
|
end
|
47
|
-
|
48
|
-
private
|
49
|
-
def ensure_local_docker_installed
|
50
|
-
docker "--version"
|
51
|
-
end
|
52
|
-
|
53
|
-
def ensure_local_buildx_installed
|
54
|
-
docker :buildx, "version"
|
55
|
-
end
|
56
42
|
end
|
@@ -1,14 +1,16 @@
|
|
1
1
|
class Kamal::Commands::Registry < Kamal::Commands::Base
|
2
|
-
|
2
|
+
def login(registry_config: nil)
|
3
|
+
registry_config ||= config.registry
|
3
4
|
|
4
|
-
def login
|
5
5
|
docker :login,
|
6
|
-
|
7
|
-
"-u", sensitive(Kamal::Utils.escape_shell_value(
|
8
|
-
"-p", sensitive(Kamal::Utils.escape_shell_value(
|
6
|
+
registry_config.server,
|
7
|
+
"-u", sensitive(Kamal::Utils.escape_shell_value(registry_config.username)),
|
8
|
+
"-p", sensitive(Kamal::Utils.escape_shell_value(registry_config.password))
|
9
9
|
end
|
10
10
|
|
11
|
-
def logout
|
12
|
-
|
11
|
+
def logout(registry_config: nil)
|
12
|
+
registry_config ||= config.registry
|
13
|
+
|
14
|
+
docker :logout, registry_config.server
|
13
15
|
end
|
14
16
|
end
|
@@ -5,7 +5,7 @@ class Kamal::Configuration::Accessory
|
|
5
5
|
|
6
6
|
delegate :argumentize, :optionize, to: Kamal::Utils
|
7
7
|
|
8
|
-
attr_reader :name, :
|
8
|
+
attr_reader :name, :env, :proxy, :registry
|
9
9
|
|
10
10
|
def initialize(name, config:)
|
11
11
|
@name, @config, @accessory_config = name.inquiry, config, config.raw_config["accessories"][name]
|
@@ -16,10 +16,11 @@ class Kamal::Configuration::Accessory
|
|
16
16
|
context: "accessories/#{name}",
|
17
17
|
with: Kamal::Configuration::Validator::Accessory
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
ensure_valid_roles
|
20
|
+
|
21
|
+
@env = initialize_env
|
22
|
+
@proxy = initialize_proxy if running_proxy?
|
23
|
+
@registry = initialize_registry if accessory_config["registry"].present?
|
23
24
|
end
|
24
25
|
|
25
26
|
def service_name
|
@@ -27,7 +28,7 @@ class Kamal::Configuration::Accessory
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def image
|
30
|
-
accessory_config["image"]
|
31
|
+
[ registry&.server, accessory_config["image"] ].compact.join("/")
|
31
32
|
end
|
32
33
|
|
33
34
|
def hosts
|
@@ -106,8 +107,33 @@ class Kamal::Configuration::Accessory
|
|
106
107
|
accessory_config["cmd"]
|
107
108
|
end
|
108
109
|
|
110
|
+
def running_proxy?
|
111
|
+
accessory_config["proxy"].present?
|
112
|
+
end
|
113
|
+
|
109
114
|
private
|
110
|
-
|
115
|
+
attr_reader :config, :accessory_config
|
116
|
+
|
117
|
+
def initialize_env
|
118
|
+
Kamal::Configuration::Env.new \
|
119
|
+
config: accessory_config.fetch("env", {}),
|
120
|
+
secrets: config.secrets,
|
121
|
+
context: "accessories/#{name}/env"
|
122
|
+
end
|
123
|
+
|
124
|
+
def initialize_proxy
|
125
|
+
Kamal::Configuration::Proxy.new \
|
126
|
+
config: config,
|
127
|
+
proxy_config: accessory_config["proxy"],
|
128
|
+
context: "accessories/#{name}/proxy"
|
129
|
+
end
|
130
|
+
|
131
|
+
def initialize_registry
|
132
|
+
Kamal::Configuration::Registry.new \
|
133
|
+
config: accessory_config,
|
134
|
+
secrets: config.secrets,
|
135
|
+
context: "accessories/#{name}/registry"
|
136
|
+
end
|
111
137
|
|
112
138
|
def default_labels
|
113
139
|
{ "service" => service_name }
|
@@ -129,7 +155,7 @@ class Kamal::Configuration::Accessory
|
|
129
155
|
end
|
130
156
|
|
131
157
|
def read_dynamic_file(local_file)
|
132
|
-
StringIO.new(ERB.new(
|
158
|
+
StringIO.new(ERB.new(File.read(local_file)).result)
|
133
159
|
end
|
134
160
|
|
135
161
|
def expand_remote_file(remote_file)
|
@@ -176,11 +202,17 @@ class Kamal::Configuration::Accessory
|
|
176
202
|
|
177
203
|
def hosts_from_roles
|
178
204
|
if accessory_config.key?("roles")
|
179
|
-
accessory_config["roles"].flat_map { |role| config.role(role)
|
205
|
+
accessory_config["roles"].flat_map { |role| config.role(role)&.hosts }
|
180
206
|
end
|
181
207
|
end
|
182
208
|
|
183
209
|
def network
|
184
210
|
accessory_config["network"] || DEFAULT_NETWORK
|
185
211
|
end
|
212
|
+
|
213
|
+
def ensure_valid_roles
|
214
|
+
if accessory_config["roles"] && (missing_roles = accessory_config["roles"] - config.roles.map(&:name)).any?
|
215
|
+
raise Kamal::ConfigurationError, "accessories/#{name}: unknown roles #{missing_roles.join(", ")}"
|
216
|
+
end
|
217
|
+
end
|
186
218
|
end
|
@@ -53,6 +53,10 @@ class Kamal::Configuration::Builder
|
|
53
53
|
!local_disabled? && (arches.empty? || local_arches.any?)
|
54
54
|
end
|
55
55
|
|
56
|
+
def cloud?
|
57
|
+
driver.start_with? "cloud"
|
58
|
+
end
|
59
|
+
|
56
60
|
def cached?
|
57
61
|
!!builder_config["cache"]
|
58
62
|
end
|
@@ -115,6 +119,10 @@ class Kamal::Configuration::Builder
|
|
115
119
|
builder_config["provenance"]
|
116
120
|
end
|
117
121
|
|
122
|
+
def sbom
|
123
|
+
builder_config["sbom"]
|
124
|
+
end
|
125
|
+
|
118
126
|
def git_clone?
|
119
127
|
Kamal::Git.used? && builder_config["context"].nil?
|
120
128
|
end
|
@@ -23,9 +23,27 @@ accessories:
|
|
23
23
|
|
24
24
|
# Image
|
25
25
|
#
|
26
|
-
# The Docker image to use
|
26
|
+
# The Docker image to use.
|
27
|
+
# Prefix it with its server when using root level registry different from Docker Hub.
|
28
|
+
# Define registry directly or via anchors when it differs from root level registry.
|
27
29
|
image: mysql:8.0
|
28
30
|
|
31
|
+
# Registry
|
32
|
+
#
|
33
|
+
# By default accessories use Docker Hub registry.
|
34
|
+
# You can specify different registry per accessory with this option.
|
35
|
+
# Don't prefix image with this registry server.
|
36
|
+
# Use anchors if you need to set the same specific registry for several accessories.
|
37
|
+
#
|
38
|
+
# ```yml
|
39
|
+
# registry:
|
40
|
+
# <<: *specific-registry
|
41
|
+
# ```
|
42
|
+
#
|
43
|
+
# See kamal docs registry for more information:
|
44
|
+
registry:
|
45
|
+
...
|
46
|
+
|
29
47
|
# Accessory hosts
|
30
48
|
#
|
31
49
|
# Specify one of `host`, `hosts`, or `roles`:
|
@@ -43,8 +61,8 @@ accessories:
|
|
43
61
|
|
44
62
|
# Port mappings
|
45
63
|
#
|
46
|
-
# See https://docs.docker.com/network
|
47
|
-
# implications of exposing ports publicly.
|
64
|
+
# See [https://docs.docker.com/network/](https://docs.docker.com/network/), and
|
65
|
+
# especially note the warning about the security implications of exposing ports publicly.
|
48
66
|
port: "127.0.0.1:3306:3306"
|
49
67
|
|
50
68
|
# Labels
|
@@ -98,3 +116,8 @@ accessories:
|
|
98
116
|
# Defaults to kamal:
|
99
117
|
network: custom
|
100
118
|
|
119
|
+
# Proxy
|
120
|
+
#
|
121
|
+
# You can run your accessory behind the Kamal proxy. See kamal docs proxy for more information
|
122
|
+
proxy:
|
123
|
+
...
|
@@ -5,12 +5,12 @@
|
|
5
5
|
# For example, for a Rails app, you might open a console with:
|
6
6
|
#
|
7
7
|
# ```shell
|
8
|
-
# kamal app exec -i
|
8
|
+
# kamal app exec -i --reuse "bin/rails console"
|
9
9
|
# ```
|
10
10
|
#
|
11
11
|
# By defining an alias, like this:
|
12
12
|
aliases:
|
13
|
-
console: app exec -
|
13
|
+
console: app exec -i --reuse "bin/rails console"
|
14
14
|
# You can now open the console with:
|
15
15
|
#
|
16
16
|
# ```shell
|
@@ -102,9 +102,18 @@ builder:
|
|
102
102
|
#
|
103
103
|
# The build driver to use, defaults to `docker-container`:
|
104
104
|
driver: docker
|
105
|
+
#
|
106
|
+
# If you want to use Docker Build Cloud (https://www.docker.com/products/build-cloud/), you can set the driver to:
|
107
|
+
driver: cloud org-name/builder-name
|
105
108
|
|
106
109
|
# Provenance
|
107
110
|
#
|
108
111
|
# It is used to configure provenance attestations for the build result.
|
109
112
|
# The value can also be a boolean to enable or disable provenance attestations.
|
110
113
|
provenance: mode=max
|
114
|
+
|
115
|
+
# SBOM (Software Bill of Materials)
|
116
|
+
#
|
117
|
+
# It is used to configure SBOM generation for the build result.
|
118
|
+
# The value can also be a boolean to enable or disable SBOM generation.
|
119
|
+
sbom: true
|
@@ -46,9 +46,22 @@ proxy:
|
|
46
46
|
# The host value must point to the server we are deploying to, and port 443 must be
|
47
47
|
# open for the Let's Encrypt challenge to succeed.
|
48
48
|
#
|
49
|
+
# If you set `ssl` to `true`, `kamal-proxy` will stop forwarding headers to your app,
|
50
|
+
# unless you explicitly set `forward_headers: true`
|
51
|
+
#
|
49
52
|
# Defaults to `false`:
|
50
53
|
ssl: true
|
51
54
|
|
55
|
+
# Forward headers
|
56
|
+
#
|
57
|
+
# Whether to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers.
|
58
|
+
#
|
59
|
+
# If you are behind a trusted proxy, you can set this to `true` to forward the headers.
|
60
|
+
#
|
61
|
+
# By default, kamal-proxy will not forward the headers if the `ssl` option is set to `true`, and
|
62
|
+
# will forward them if it is set to `false`.
|
63
|
+
forward_headers: true
|
64
|
+
|
52
65
|
# Response timeout
|
53
66
|
#
|
54
67
|
# How long to wait for requests to complete before timing out, defaults to 30 seconds:
|
@@ -93,13 +106,3 @@ proxy:
|
|
93
106
|
response_headers:
|
94
107
|
- X-Request-ID
|
95
108
|
- X-Request-Start
|
96
|
-
|
97
|
-
# Forward headers
|
98
|
-
#
|
99
|
-
# Whether to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers.
|
100
|
-
#
|
101
|
-
# If you are behind a trusted proxy, you can set this to `true` to forward the headers.
|
102
|
-
#
|
103
|
-
# By default, kamal-proxy will not forward the headers if the `ssl` option is set to `true`, and
|
104
|
-
# will forward them if it is set to `false`.
|
105
|
-
forward_headers: true
|
@@ -2,6 +2,10 @@
|
|
2
2
|
#
|
3
3
|
# The default registry is Docker Hub, but you can change it using `registry/server`.
|
4
4
|
#
|
5
|
+
# By default, Docker Hub creates public repositories. To avoid making your images public,
|
6
|
+
# set up a private repository before deploying, or change the default repository privacy
|
7
|
+
# settings to private in your [Docker Hub settings](https://hub.docker.com/repository-settings/default-privacy).
|
8
|
+
#
|
5
9
|
# A reference to a secret (in this case, `DOCKER_REGISTRY_TOKEN`) will look up the secret
|
6
10
|
# in the local environment:
|
7
11
|
registry:
|
@@ -1,12 +1,10 @@
|
|
1
1
|
class Kamal::Configuration::Registry
|
2
2
|
include Kamal::Configuration::Validation
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@secrets = config.secrets
|
9
|
-
validate! registry_config, with: Kamal::Configuration::Validator::Registry
|
4
|
+
def initialize(config:, secrets:, context: "registry")
|
5
|
+
@registry_config = config["registry"] || {}
|
6
|
+
@secrets = secrets
|
7
|
+
validate! registry_config, context: context, with: Kamal::Configuration::Validator::Registry
|
10
8
|
end
|
11
9
|
|
12
10
|
def server
|
@@ -22,6 +20,8 @@ class Kamal::Configuration::Registry
|
|
22
20
|
end
|
23
21
|
|
24
22
|
private
|
23
|
+
attr_reader :registry_config, :secrets
|
24
|
+
|
25
25
|
def lookup(key)
|
26
26
|
if registry_config[key].is_a?(Array)
|
27
27
|
secrets[registry_config[key].first]
|
@@ -10,7 +10,7 @@ class Kamal::Configuration::Role
|
|
10
10
|
def initialize(name, config:)
|
11
11
|
@name, @config = name.inquiry, config
|
12
12
|
validate! \
|
13
|
-
|
13
|
+
role_config,
|
14
14
|
example: validation_yml["servers"]["workers"],
|
15
15
|
context: "servers/#{name}",
|
16
16
|
with: Kamal::Configuration::Validator::Role
|
@@ -204,11 +204,11 @@ class Kamal::Configuration::Role
|
|
204
204
|
end
|
205
205
|
|
206
206
|
def specializations
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
207
|
+
@specializations ||= role_config.is_a?(Array) ? {} : role_config
|
208
|
+
end
|
209
|
+
|
210
|
+
def role_config
|
211
|
+
@role_config ||= config.raw_config.servers.is_a?(Array) ? {} : config.raw_config.servers[name]
|
212
212
|
end
|
213
213
|
|
214
214
|
def custom_labels
|