kamal 2.3.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|