kamal 2.6.1 → 2.8.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 +15 -2
- data/lib/kamal/cli/app/ssl_certificates.rb +28 -0
- data/lib/kamal/cli/app.rb +1 -0
- data/lib/kamal/cli/build.rb +33 -15
- data/lib/kamal/cli/main.rb +7 -2
- data/lib/kamal/cli/port_forwarding.rb +42 -0
- data/lib/kamal/cli/registry.rb +16 -8
- data/lib/kamal/cli/templates/deploy.yml +4 -3
- data/lib/kamal/cli/templates/sample_hooks/pre-deploy.sample +13 -1
- data/lib/kamal/cli/templates/secrets +1 -1
- data/lib/kamal/commander.rb +1 -1
- data/lib/kamal/commands/accessory.rb +8 -3
- data/lib/kamal/commands/app/execution.rb +2 -2
- data/lib/kamal/commands/app/proxy.rb +4 -0
- data/lib/kamal/commands/app.rb +4 -2
- data/lib/kamal/commands/base.rb +8 -0
- data/lib/kamal/commands/builder/base.rb +11 -1
- data/lib/kamal/commands/builder/local.rb +15 -2
- data/lib/kamal/commands/builder/pack.rb +46 -0
- data/lib/kamal/commands/builder/remote.rb +9 -1
- data/lib/kamal/commands/builder.rb +14 -2
- data/lib/kamal/commands/registry.rb +22 -0
- data/lib/kamal/configuration/accessory.rb +2 -1
- data/lib/kamal/configuration/builder.rb +12 -0
- data/lib/kamal/configuration/docs/builder.yml +13 -0
- data/lib/kamal/configuration/docs/proxy.yml +39 -0
- data/lib/kamal/configuration/proxy/boot.rb +8 -0
- data/lib/kamal/configuration/proxy.rb +52 -4
- data/lib/kamal/configuration/registry.rb +8 -0
- data/lib/kamal/configuration/role.rb +5 -3
- data/lib/kamal/configuration/validator/accessory.rb +2 -0
- data/lib/kamal/configuration/validator/builder.rb +2 -0
- data/lib/kamal/configuration/validator/proxy.rb +10 -0
- data/lib/kamal/configuration/validator/registry.rb +5 -3
- data/lib/kamal/configuration/validator/role.rb +1 -0
- data/lib/kamal/configuration/validator.rb +14 -0
- data/lib/kamal/configuration.rb +12 -3
- data/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb +10 -16
- data/lib/kamal/secrets/adapters/one_password.rb +45 -11
- data/lib/kamal/secrets/adapters/passbolt.rb +130 -0
- data/lib/kamal/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80ba6d51041312c99d659a1bfaac13bfa0ed7d1e758bde65e5475c0e51d88238
|
|
4
|
+
data.tar.gz: f0cc94a905da2cfb5dcf4f5d9ead2194df1b0ed46fd3b8671a59bfc333b10fbf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e33ddb40f46e587364d9121bbd2f2d829beddeb956f4bf1d8399e5ac835285180914f51e1365bee96ec4b82a02c0e88df8ff513a68bf95e44a8dc7e0ce081509
|
|
7
|
+
data.tar.gz: 8a0b1a90bbacd96d072cbbe5cec3371e5f7fe6d213cfa5dac3203f6d4ef02fadbddd1e3458909f3051adcd9218d69d6edb5b193f86fca6fac28b49b00bd2dd91
|
data/lib/kamal/cli/accessory.rb
CHANGED
|
@@ -24,11 +24,11 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
|
24
24
|
directories(name)
|
|
25
25
|
upload(name)
|
|
26
26
|
|
|
27
|
-
on(hosts) do
|
|
27
|
+
on(hosts) do |host|
|
|
28
28
|
execute *KAMAL.auditor.record("Booted #{name} accessory"), verbosity: :debug
|
|
29
29
|
execute *accessory.ensure_env_directory
|
|
30
30
|
upload! accessory.secrets_io, accessory.secrets_path, mode: "0600"
|
|
31
|
-
execute *accessory.run
|
|
31
|
+
execute *accessory.run(host: host)
|
|
32
32
|
|
|
33
33
|
if accessory.running_proxy?
|
|
34
34
|
target = capture_with_info(*accessory.container_id_for(container_name: accessory.service_name, only_running: true)).strip
|
|
@@ -77,6 +77,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
|
77
77
|
KAMAL.accessory_names.each { |accessory_name| reboot(accessory_name) }
|
|
78
78
|
else
|
|
79
79
|
prepare(name)
|
|
80
|
+
pull_image(name)
|
|
80
81
|
stop(name)
|
|
81
82
|
remove_container(name)
|
|
82
83
|
boot(name, prepare: false)
|
|
@@ -203,6 +204,18 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
|
203
204
|
end
|
|
204
205
|
end
|
|
205
206
|
|
|
207
|
+
desc "pull_image [NAME]", "Pull accessory image on host", hide: true
|
|
208
|
+
def pull_image(name)
|
|
209
|
+
with_lock do
|
|
210
|
+
with_accessory(name) do |accessory, hosts|
|
|
211
|
+
on(hosts) do
|
|
212
|
+
execute *KAMAL.auditor.record("Pull #{name} accessory image"), verbosity: :debug
|
|
213
|
+
execute *accessory.pull_image
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
206
219
|
desc "remove [NAME]", "Remove accessory container, image and data directory from host (use NAME=all to remove all accessories)"
|
|
207
220
|
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
|
208
221
|
def remove(name)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class Kamal::Cli::App::SslCertificates
|
|
2
|
+
attr_reader :host, :role, :sshkit
|
|
3
|
+
delegate :execute, :info, :upload!, to: :sshkit
|
|
4
|
+
|
|
5
|
+
def initialize(host, role, sshkit)
|
|
6
|
+
@host = host
|
|
7
|
+
@role = role
|
|
8
|
+
@sshkit = sshkit
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
if role.running_proxy? && role.proxy.custom_ssl_certificate?
|
|
13
|
+
info "Writing SSL certificates for #{role.name} on #{host}"
|
|
14
|
+
execute *app.create_ssl_directory
|
|
15
|
+
if cert_content = role.proxy.certificate_pem_content
|
|
16
|
+
upload!(StringIO.new(cert_content), role.proxy.host_tls_cert, mode: "0644")
|
|
17
|
+
end
|
|
18
|
+
if key_content = role.proxy.private_key_pem_content
|
|
19
|
+
upload!(StringIO.new(key_content), role.proxy.host_tls_key, mode: "0644")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
def app
|
|
26
|
+
@app ||= KAMAL.app(role: role, host: host)
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/kamal/cli/app.rb
CHANGED
data/lib/kamal/cli/build.rb
CHANGED
|
@@ -11,6 +11,7 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
11
11
|
|
|
12
12
|
desc "push", "Build and push app image to registry"
|
|
13
13
|
option :output, type: :string, default: "registry", banner: "export_type", desc: "Exported type for the build result, and may be any exported type supported by 'buildx --output'."
|
|
14
|
+
option :no_cache, type: :boolean, default: false, desc: "Build without using Docker's build cache"
|
|
14
15
|
def push
|
|
15
16
|
cli = self
|
|
16
17
|
|
|
@@ -19,7 +20,7 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
19
20
|
pre_connect_if_required
|
|
20
21
|
|
|
21
22
|
ensure_docker_installed
|
|
22
|
-
login_to_registry_locally
|
|
23
|
+
login_to_registry_locally if KAMAL.builder.login_to_registry_locally?
|
|
23
24
|
|
|
24
25
|
run_hook "pre-build"
|
|
25
26
|
|
|
@@ -56,10 +57,10 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
# Get the command here to ensure the Dir.chdir doesn't interfere with it
|
|
59
|
-
push = KAMAL.builder.push(cli.options[:output])
|
|
60
|
+
push = KAMAL.builder.push(cli.options[:output], no_cache: cli.options[:no_cache])
|
|
60
61
|
|
|
61
62
|
KAMAL.with_verbosity(:debug) do
|
|
62
|
-
Dir.chdir(KAMAL.config.builder.build_directory) { execute *push }
|
|
63
|
+
Dir.chdir(KAMAL.config.builder.build_directory) { execute *push, env: KAMAL.builder.push_env }
|
|
63
64
|
end
|
|
64
65
|
end
|
|
65
66
|
end
|
|
@@ -67,16 +68,18 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
67
68
|
|
|
68
69
|
desc "pull", "Pull app image from registry onto servers"
|
|
69
70
|
def pull
|
|
70
|
-
login_to_registry_remotely
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
login_to_registry_remotely unless KAMAL.registry.local?
|
|
72
|
+
|
|
73
|
+
forward_local_registry_port do
|
|
74
|
+
if (first_hosts = mirror_hosts).any?
|
|
75
|
+
# Pull on a single host per mirror first to seed them
|
|
76
|
+
say "Pulling image on #{first_hosts.join(", ")} to seed the #{"mirror".pluralize(first_hosts.count)}...", :magenta
|
|
77
|
+
pull_on_hosts(first_hosts)
|
|
78
|
+
say "Pulling image on remaining hosts...", :magenta
|
|
79
|
+
pull_on_hosts(KAMAL.app_hosts - first_hosts)
|
|
80
|
+
else
|
|
81
|
+
pull_on_hosts(KAMAL.app_hosts)
|
|
82
|
+
end
|
|
80
83
|
end
|
|
81
84
|
end
|
|
82
85
|
|
|
@@ -119,6 +122,7 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
119
122
|
|
|
120
123
|
desc "dev", "Build using the working directory, tag it as dirty, and push to local image store."
|
|
121
124
|
option :output, type: :string, default: "docker", banner: "export_type", desc: "Exported type for the build result, and may be any exported type supported by 'buildx --output'."
|
|
125
|
+
option :no_cache, type: :boolean, default: false, desc: "Build without using Docker's build cache"
|
|
122
126
|
def dev
|
|
123
127
|
cli = self
|
|
124
128
|
|
|
@@ -144,7 +148,7 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
144
148
|
|
|
145
149
|
with_env(KAMAL.config.builder.secrets) do
|
|
146
150
|
run_locally do
|
|
147
|
-
build = KAMAL.builder.push(cli.options[:output], tag_as_dirty: true)
|
|
151
|
+
build = KAMAL.builder.push(cli.options[:output], tag_as_dirty: true, no_cache: cli.options[:no_cache])
|
|
148
152
|
KAMAL.with_verbosity(:debug) do
|
|
149
153
|
execute(*build)
|
|
150
154
|
end
|
|
@@ -192,7 +196,11 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
192
196
|
|
|
193
197
|
def login_to_registry_locally
|
|
194
198
|
run_locally do
|
|
195
|
-
|
|
199
|
+
if KAMAL.registry.local?
|
|
200
|
+
execute *KAMAL.registry.setup
|
|
201
|
+
else
|
|
202
|
+
execute *KAMAL.registry.login
|
|
203
|
+
end
|
|
196
204
|
end
|
|
197
205
|
end
|
|
198
206
|
|
|
@@ -201,4 +209,14 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
|
201
209
|
execute *KAMAL.registry.login
|
|
202
210
|
end
|
|
203
211
|
end
|
|
212
|
+
|
|
213
|
+
def forward_local_registry_port(&block)
|
|
214
|
+
if KAMAL.config.registry.local?
|
|
215
|
+
Kamal::Cli::PortForwarding.
|
|
216
|
+
new(KAMAL.hosts, KAMAL.config.registry.local_port).
|
|
217
|
+
forward(&block)
|
|
218
|
+
else
|
|
219
|
+
yield
|
|
220
|
+
end
|
|
221
|
+
end
|
|
204
222
|
end
|
data/lib/kamal/cli/main.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
class Kamal::Cli::Main < Kamal::Cli::Base
|
|
2
2
|
desc "setup", "Setup all accessories, push the env, and deploy app to servers"
|
|
3
3
|
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
|
4
|
+
option :no_cache, type: :boolean, default: false, desc: "Build without using Docker's build cache"
|
|
4
5
|
def setup
|
|
5
6
|
print_runtime do
|
|
6
7
|
with_lock do
|
|
@@ -16,6 +17,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
16
17
|
|
|
17
18
|
desc "deploy", "Deploy app to servers"
|
|
18
19
|
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
|
20
|
+
option :no_cache, type: :boolean, default: false, desc: "Build without using Docker's build cache"
|
|
19
21
|
def deploy(boot_accessories: false)
|
|
20
22
|
runtime = print_runtime do
|
|
21
23
|
invoke_options = deploy_options
|
|
@@ -51,6 +53,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
51
53
|
|
|
52
54
|
desc "redeploy", "Deploy app to servers without bootstrapping servers, starting kamal-proxy and pruning"
|
|
53
55
|
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
|
56
|
+
option :no_cache, type: :boolean, default: false, desc: "Build without using Docker's build cache"
|
|
54
57
|
def redeploy
|
|
55
58
|
runtime = print_runtime do
|
|
56
59
|
invoke_options = deploy_options
|
|
@@ -182,7 +185,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
182
185
|
invoke "kamal:cli:app:remove", [], options.without(:confirmed)
|
|
183
186
|
invoke "kamal:cli:proxy:remove", [], options.without(:confirmed)
|
|
184
187
|
invoke "kamal:cli:accessory:remove", [ "all" ], options
|
|
185
|
-
invoke "kamal:cli:registry:
|
|
188
|
+
invoke "kamal:cli:registry:remove", [], options.without(:confirmed).merge(skip_local: true)
|
|
186
189
|
end
|
|
187
190
|
end
|
|
188
191
|
end
|
|
@@ -272,6 +275,8 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|
|
272
275
|
end
|
|
273
276
|
|
|
274
277
|
def deploy_options
|
|
275
|
-
|
|
278
|
+
base_options = options.without("skip_push")
|
|
279
|
+
base_options = base_options.except("no_cache") unless base_options["no_cache"]
|
|
280
|
+
{ "version" => KAMAL.config.version }.merge(base_options)
|
|
276
281
|
end
|
|
277
282
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class Kamal::Cli::PortForwarding
|
|
2
|
+
attr_reader :hosts, :port
|
|
3
|
+
|
|
4
|
+
def initialize(hosts, port)
|
|
5
|
+
@hosts = hosts
|
|
6
|
+
@port = port
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def forward
|
|
10
|
+
@done = false
|
|
11
|
+
forward_ports
|
|
12
|
+
|
|
13
|
+
yield
|
|
14
|
+
ensure
|
|
15
|
+
stop
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def stop
|
|
21
|
+
@done = true
|
|
22
|
+
@threads.to_a.each(&:join)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def forward_ports
|
|
26
|
+
@threads = hosts.map do |host|
|
|
27
|
+
Thread.new do
|
|
28
|
+
Net::SSH.start(host, KAMAL.config.ssh.user, **{ proxy: KAMAL.config.ssh.proxy }.compact) do |ssh|
|
|
29
|
+
ssh.forward.remote(port, "localhost", port, "localhost")
|
|
30
|
+
ssh.loop(0.1) do
|
|
31
|
+
if @done
|
|
32
|
+
ssh.forward.cancel_remote(port, "localhost")
|
|
33
|
+
break
|
|
34
|
+
else
|
|
35
|
+
true
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/kamal/cli/registry.rb
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
class Kamal::Cli::Registry < Kamal::Cli::Base
|
|
2
|
-
desc "
|
|
2
|
+
desc "setup", "Setup local registry or log in to remote registry locally and remotely"
|
|
3
3
|
option :skip_local, aliases: "-L", type: :boolean, default: false, desc: "Skip local login"
|
|
4
4
|
option :skip_remote, aliases: "-R", type: :boolean, default: false, desc: "Skip remote login"
|
|
5
|
-
def
|
|
5
|
+
def setup
|
|
6
6
|
ensure_docker_installed unless options[:skip_local]
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
if KAMAL.registry.local?
|
|
9
|
+
run_locally { execute *KAMAL.registry.setup } unless options[:skip_local]
|
|
10
|
+
else
|
|
11
|
+
run_locally { execute *KAMAL.registry.login } unless options[:skip_local]
|
|
12
|
+
on(KAMAL.hosts) { execute *KAMAL.registry.login } unless options[:skip_remote]
|
|
13
|
+
end
|
|
10
14
|
end
|
|
11
15
|
|
|
12
|
-
desc "
|
|
16
|
+
desc "remove", "Remove local registry or log out of remote registry locally and remotely"
|
|
13
17
|
option :skip_local, aliases: "-L", type: :boolean, default: false, desc: "Skip local login"
|
|
14
18
|
option :skip_remote, aliases: "-R", type: :boolean, default: false, desc: "Skip remote login"
|
|
15
|
-
def
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
def remove
|
|
20
|
+
if KAMAL.registry.local?
|
|
21
|
+
run_locally { execute *KAMAL.registry.remove, raise_on_non_zero_exit: false } unless options[:skip_local]
|
|
22
|
+
else
|
|
23
|
+
run_locally { execute *KAMAL.registry.logout } unless options[:skip_local]
|
|
24
|
+
on(KAMAL.hosts) { execute *KAMAL.registry.logout } unless options[:skip_remote]
|
|
25
|
+
end
|
|
18
26
|
end
|
|
19
27
|
end
|
|
@@ -25,13 +25,14 @@ proxy:
|
|
|
25
25
|
|
|
26
26
|
# Credentials for your image host.
|
|
27
27
|
registry:
|
|
28
|
+
server: localhost:5555
|
|
28
29
|
# Specify the registry server, if you're not using Docker Hub
|
|
29
30
|
# server: registry.digitalocean.com / ghcr.io / ...
|
|
30
|
-
username: my-user
|
|
31
|
+
# username: my-user
|
|
31
32
|
|
|
32
33
|
# Always use an access token rather than real password (pulled from .kamal/secrets).
|
|
33
|
-
password:
|
|
34
|
-
|
|
34
|
+
# password:
|
|
35
|
+
# - KAMAL_REGISTRY_PASSWORD
|
|
35
36
|
|
|
36
37
|
# Configure builder setup.
|
|
37
38
|
builder:
|
|
@@ -43,7 +43,7 @@ class GithubStatusChecks
|
|
|
43
43
|
attr_reader :remote_url, :git_sha, :github_client, :combined_status
|
|
44
44
|
|
|
45
45
|
def initialize
|
|
46
|
-
@remote_url =
|
|
46
|
+
@remote_url = github_repo_from_remote_url
|
|
47
47
|
@git_sha = `git rev-parse HEAD`.strip
|
|
48
48
|
@github_client = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])
|
|
49
49
|
refresh!
|
|
@@ -77,6 +77,18 @@ class GithubStatusChecks
|
|
|
77
77
|
"Build not started..."
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
def github_repo_from_remote_url
|
|
83
|
+
url = `git config --get remote.origin.url`.strip.delete_suffix(".git")
|
|
84
|
+
if url.start_with?("https://github.com/")
|
|
85
|
+
url.delete_prefix("https://github.com/")
|
|
86
|
+
elsif url.start_with?("git@github.com:")
|
|
87
|
+
url.delete_prefix("git@github.com:")
|
|
88
|
+
else
|
|
89
|
+
url
|
|
90
|
+
end
|
|
91
|
+
end
|
|
80
92
|
end
|
|
81
93
|
|
|
82
94
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# password manager, ENV, or a file. DO NOT ENTER RAW CREDENTIALS HERE! This file needs to be safe for git.
|
|
4
4
|
|
|
5
5
|
# Option 1: Read secrets from the environment
|
|
6
|
-
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
|
|
6
|
+
# KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
|
|
7
7
|
|
|
8
8
|
# Option 2: Read secrets via a command
|
|
9
9
|
# RAILS_MASTER_KEY=$(cat config/master.key)
|
data/lib/kamal/commander.rb
CHANGED
|
@@ -21,7 +21,7 @@ class Kamal::Commander
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def config
|
|
24
|
-
@config ||= Kamal::Configuration.create_from(**@config_kwargs).tap do |config|
|
|
24
|
+
@config ||= Kamal::Configuration.create_from(**@config_kwargs.to_h).tap do |config|
|
|
25
25
|
@config_kwargs = nil
|
|
26
26
|
configure_sshkit_with(config)
|
|
27
27
|
end
|
|
@@ -12,7 +12,7 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
|
12
12
|
@accessory_config = config.accessory(name)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def run
|
|
15
|
+
def run(host: nil)
|
|
16
16
|
docker :run,
|
|
17
17
|
"--name", service_name,
|
|
18
18
|
"--detach",
|
|
@@ -20,6 +20,7 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
|
20
20
|
*network_args,
|
|
21
21
|
*config.logging_args,
|
|
22
22
|
*publish_args,
|
|
23
|
+
*([ "--env", "KAMAL_HOST=\"#{host}\"" ] if host),
|
|
23
24
|
*env_args,
|
|
24
25
|
*volume_args,
|
|
25
26
|
*label_args,
|
|
@@ -55,14 +56,14 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
|
55
56
|
|
|
56
57
|
def execute_in_existing_container(*command, interactive: false)
|
|
57
58
|
docker :exec,
|
|
58
|
-
(
|
|
59
|
+
(docker_interactive_args if interactive),
|
|
59
60
|
service_name,
|
|
60
61
|
*command
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
def execute_in_new_container(*command, interactive: false)
|
|
64
65
|
docker :run,
|
|
65
|
-
(
|
|
66
|
+
(docker_interactive_args if interactive),
|
|
66
67
|
"--rm",
|
|
67
68
|
*network_args,
|
|
68
69
|
*env_args,
|
|
@@ -89,6 +90,10 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|
|
89
90
|
end
|
|
90
91
|
end
|
|
91
92
|
|
|
93
|
+
def pull_image
|
|
94
|
+
docker :image, :pull, image
|
|
95
|
+
end
|
|
96
|
+
|
|
92
97
|
def remove_service_directory
|
|
93
98
|
[ :rm, "-rf", service_name ]
|
|
94
99
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Kamal::Commands::App::Execution
|
|
2
2
|
def execute_in_existing_container(*command, interactive: false, env:)
|
|
3
3
|
docker :exec,
|
|
4
|
-
(
|
|
4
|
+
(docker_interactive_args if interactive),
|
|
5
5
|
*argumentize("--env", env),
|
|
6
6
|
container_name,
|
|
7
7
|
*command
|
|
@@ -9,7 +9,7 @@ module Kamal::Commands::App::Execution
|
|
|
9
9
|
|
|
10
10
|
def execute_in_new_container(*command, interactive: false, detach: false, env:)
|
|
11
11
|
docker :run,
|
|
12
|
-
(
|
|
12
|
+
(docker_interactive_args if interactive),
|
|
13
13
|
("--detach" if detach),
|
|
14
14
|
("--rm" unless detach),
|
|
15
15
|
"--network", "kamal",
|
|
@@ -21,6 +21,10 @@ module Kamal::Commands::App::Proxy
|
|
|
21
21
|
remove_directory config.proxy_boot.app_directory
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def create_ssl_directory
|
|
25
|
+
make_directory(File.join(config.proxy_boot.tls_directory, role.name))
|
|
26
|
+
end
|
|
27
|
+
|
|
24
28
|
private
|
|
25
29
|
def proxy_exec(*command)
|
|
26
30
|
docker :exec, proxy_container_name, "kamal-proxy", *command
|
data/lib/kamal/commands/app.rb
CHANGED
|
@@ -20,8 +20,10 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|
|
20
20
|
"--name", container_name,
|
|
21
21
|
"--network", "kamal",
|
|
22
22
|
*([ "--hostname", hostname ] if hostname),
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
"--env", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
|
24
|
+
"--env", "KAMAL_VERSION=\"#{config.version}\"",
|
|
25
|
+
"--env", "KAMAL_HOST=\"#{host}\"",
|
|
26
|
+
"--env", "KAMAL_DESTINATION=\"#{config.destination}\"",
|
|
25
27
|
*role.env_args(host),
|
|
26
28
|
*role.logging_args,
|
|
27
29
|
*config.volume_args,
|
data/lib/kamal/commands/base.rb
CHANGED
|
@@ -84,6 +84,10 @@ module Kamal::Commands
|
|
|
84
84
|
args.compact.unshift :docker
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
def pack(*args)
|
|
88
|
+
args.compact.unshift :pack
|
|
89
|
+
end
|
|
90
|
+
|
|
87
91
|
def git(*args, path: nil)
|
|
88
92
|
[ :git, *([ "-C", path ] if path), *args.compact ]
|
|
89
93
|
end
|
|
@@ -122,5 +126,9 @@ module Kamal::Commands
|
|
|
122
126
|
def ensure_local_buildx_installed
|
|
123
127
|
docker :buildx, "version"
|
|
124
128
|
end
|
|
129
|
+
|
|
130
|
+
def docker_interactive_args
|
|
131
|
+
STDIN.isatty ? "-it" : "-i"
|
|
132
|
+
end
|
|
125
133
|
end
|
|
126
134
|
end
|
|
@@ -6,6 +6,7 @@ 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
|
+
:pack?, :pack_builder, :pack_buildpacks,
|
|
9
10
|
:cache_from, :cache_to, :ssh, :provenance, :sbom, :driver, :docker_driver?,
|
|
10
11
|
to: :builder_config
|
|
11
12
|
|
|
@@ -13,13 +14,14 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
|
13
14
|
docker :image, :rm, "--force", config.absolute_image
|
|
14
15
|
end
|
|
15
16
|
|
|
16
|
-
def push(export_action = "registry", tag_as_dirty: false)
|
|
17
|
+
def push(export_action = "registry", tag_as_dirty: false, no_cache: false)
|
|
17
18
|
docker :buildx, :build,
|
|
18
19
|
"--output=type=#{export_action}",
|
|
19
20
|
*platform_options(arches),
|
|
20
21
|
*([ "--builder", builder_name ] unless docker_driver?),
|
|
21
22
|
*build_tag_options(tag_as_dirty: tag_as_dirty),
|
|
22
23
|
*build_options,
|
|
24
|
+
*([ "--no-cache" ] if no_cache),
|
|
23
25
|
build_context,
|
|
24
26
|
"2>&1"
|
|
25
27
|
end
|
|
@@ -59,6 +61,14 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|
|
59
61
|
docker(:info, "--format '{{index .RegistryConfig.Mirrors 0}}'")
|
|
60
62
|
end
|
|
61
63
|
|
|
64
|
+
def login_to_registry_locally?
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def push_env
|
|
69
|
+
{}
|
|
70
|
+
end
|
|
71
|
+
|
|
62
72
|
private
|
|
63
73
|
def build_tag_names(tag_as_dirty: false)
|
|
64
74
|
tag_names = [ config.absolute_image, config.latest_image ]
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
class Kamal::Commands::Builder::Local < Kamal::Commands::Builder::Base
|
|
2
2
|
def create
|
|
3
|
-
|
|
3
|
+
return if docker_driver?
|
|
4
|
+
|
|
5
|
+
options =
|
|
6
|
+
if KAMAL.registry.local?
|
|
7
|
+
"--driver=#{driver} --driver-opt network=host"
|
|
8
|
+
else
|
|
9
|
+
"--driver=#{driver}"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
docker :buildx, :create, "--name", builder_name, options
|
|
4
13
|
end
|
|
5
14
|
|
|
6
15
|
def remove
|
|
@@ -9,6 +18,10 @@ class Kamal::Commands::Builder::Local < Kamal::Commands::Builder::Base
|
|
|
9
18
|
|
|
10
19
|
private
|
|
11
20
|
def builder_name
|
|
12
|
-
|
|
21
|
+
if KAMAL.registry.local?
|
|
22
|
+
"kamal-local-registry-#{driver}"
|
|
23
|
+
else
|
|
24
|
+
"kamal-local-#{driver}"
|
|
25
|
+
end
|
|
13
26
|
end
|
|
14
27
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class Kamal::Commands::Builder::Pack < Kamal::Commands::Builder::Base
|
|
2
|
+
def push(export_action = "registry", tag_as_dirty: false, no_cache: false)
|
|
3
|
+
combine \
|
|
4
|
+
build(tag_as_dirty: tag_as_dirty, no_cache: no_cache),
|
|
5
|
+
export(export_action)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def remove;end
|
|
9
|
+
|
|
10
|
+
def info
|
|
11
|
+
pack :builder, :inspect, pack_builder
|
|
12
|
+
end
|
|
13
|
+
alias_method :inspect_builder, :info
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
def build(tag_as_dirty: false, no_cache: false)
|
|
17
|
+
pack(:build,
|
|
18
|
+
config.repository,
|
|
19
|
+
"--platform", platform,
|
|
20
|
+
"--creation-time", "now",
|
|
21
|
+
"--builder", pack_builder,
|
|
22
|
+
buildpacks,
|
|
23
|
+
*build_tag_options(tag_as_dirty: tag_as_dirty),
|
|
24
|
+
*([ "--clear-cache" ] if no_cache),
|
|
25
|
+
"--env", "BP_IMAGE_LABELS=service=#{config.service}",
|
|
26
|
+
*argumentize("--env", args),
|
|
27
|
+
*argumentize("--env", secrets, sensitive: true),
|
|
28
|
+
"--path", build_context)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def export(export_action)
|
|
32
|
+
return unless export_action == "registry"
|
|
33
|
+
|
|
34
|
+
combine \
|
|
35
|
+
docker(:push, config.absolute_image),
|
|
36
|
+
docker(:push, config.latest_image)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def platform
|
|
40
|
+
"linux/#{local_arches.first}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def buildpacks
|
|
44
|
+
(pack_buildpacks << "paketo-buildpacks/image-labels").map { |buildpack| [ "--buildpack", buildpack ] }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -19,11 +19,19 @@ class Kamal::Commands::Builder::Remote < Kamal::Commands::Builder::Base
|
|
|
19
19
|
|
|
20
20
|
def inspect_builder
|
|
21
21
|
combine \
|
|
22
|
-
combine
|
|
22
|
+
combine(inspect_buildx, inspect_remote_context),
|
|
23
23
|
[ "(echo no compatible builder && exit 1)" ],
|
|
24
24
|
by: "||"
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
def login_to_registry_locally?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def push_env
|
|
32
|
+
{ "BUILDKIT_NO_CLIENT_TOKEN" => "1" }
|
|
33
|
+
end
|
|
34
|
+
|
|
27
35
|
private
|
|
28
36
|
def builder_name
|
|
29
37
|
"kamal-remote-#{remote.gsub(/[^a-z0-9_-]/, "-")}"
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
require "active_support/core_ext/string/filters"
|
|
2
2
|
|
|
3
3
|
class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
4
|
-
delegate
|
|
5
|
-
|
|
4
|
+
delegate \
|
|
5
|
+
:create, :remove, :dev, :push, :clean, :pull, :info, :inspect_builder,
|
|
6
|
+
:validate_image, :first_mirror, :login_to_registry_locally?, :push_env,
|
|
7
|
+
to: :target
|
|
8
|
+
|
|
9
|
+
delegate \
|
|
10
|
+
:local?, :remote?, :pack?, :cloud?,
|
|
11
|
+
to: "config.builder"
|
|
6
12
|
|
|
7
13
|
include Clone
|
|
8
14
|
|
|
@@ -17,6 +23,8 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
|
17
23
|
else
|
|
18
24
|
remote
|
|
19
25
|
end
|
|
26
|
+
elsif pack?
|
|
27
|
+
pack
|
|
20
28
|
elsif cloud?
|
|
21
29
|
cloud
|
|
22
30
|
else
|
|
@@ -36,6 +44,10 @@ class Kamal::Commands::Builder < Kamal::Commands::Base
|
|
|
36
44
|
@hybrid ||= Kamal::Commands::Builder::Hybrid.new(config)
|
|
37
45
|
end
|
|
38
46
|
|
|
47
|
+
def pack
|
|
48
|
+
@pack ||= Kamal::Commands::Builder::Pack.new(config)
|
|
49
|
+
end
|
|
50
|
+
|
|
39
51
|
def cloud
|
|
40
52
|
@cloud ||= Kamal::Commands::Builder::Cloud.new(config)
|
|
41
53
|
end
|