kamal 2.0.0.alpha → 2.0.0.beta1

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/kamal/cli/accessory.rb +44 -20
  4. data/lib/kamal/cli/app/boot.rb +22 -16
  5. data/lib/kamal/cli/app.rb +37 -3
  6. data/lib/kamal/cli/base.rb +9 -48
  7. data/lib/kamal/cli/build.rb +8 -3
  8. data/lib/kamal/cli/healthcheck/barrier.rb +2 -0
  9. data/lib/kamal/cli/healthcheck/poller.rb +18 -39
  10. data/lib/kamal/cli/lock.rb +2 -3
  11. data/lib/kamal/cli/main.rb +54 -51
  12. data/lib/kamal/cli/proxy.rb +224 -0
  13. data/lib/kamal/cli/prune.rb +0 -1
  14. data/lib/kamal/cli/secrets.rb +36 -0
  15. data/lib/kamal/cli/server.rb +0 -2
  16. data/lib/kamal/cli/templates/deploy.yml +0 -11
  17. data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
  18. data/lib/kamal/cli/templates/secrets +16 -0
  19. data/lib/kamal/cli.rb +1 -0
  20. data/lib/kamal/commander/specifics.rb +3 -3
  21. data/lib/kamal/commander.rb +17 -9
  22. data/lib/kamal/commands/accessory.rb +7 -7
  23. data/lib/kamal/commands/app/assets.rb +8 -8
  24. data/lib/kamal/commands/app/proxy.rb +16 -0
  25. data/lib/kamal/commands/app.rb +7 -15
  26. data/lib/kamal/commands/auditor.rb +6 -3
  27. data/lib/kamal/commands/base.rb +8 -0
  28. data/lib/kamal/commands/builder/base.rb +2 -6
  29. data/lib/kamal/commands/builder/hybrid.rb +1 -1
  30. data/lib/kamal/commands/builder/remote.rb +27 -4
  31. data/lib/kamal/commands/builder.rb +1 -1
  32. data/lib/kamal/commands/docker.rb +4 -0
  33. data/lib/kamal/commands/hook.rb +5 -2
  34. data/lib/kamal/commands/lock.rb +2 -6
  35. data/lib/kamal/commands/proxy.rb +77 -0
  36. data/lib/kamal/commands/prune.rb +1 -9
  37. data/lib/kamal/commands/server.rb +11 -1
  38. data/lib/kamal/configuration/accessory.rb +14 -2
  39. data/lib/kamal/configuration/builder.rb +9 -3
  40. data/lib/kamal/configuration/docs/builder.yml +20 -10
  41. data/lib/kamal/configuration/docs/configuration.yml +16 -16
  42. data/lib/kamal/configuration/docs/env.yml +10 -11
  43. data/lib/kamal/configuration/docs/proxy.yml +100 -0
  44. data/lib/kamal/configuration/docs/registry.yml +4 -2
  45. data/lib/kamal/configuration/docs/role.yml +3 -5
  46. data/lib/kamal/configuration/env/tag.rb +4 -3
  47. data/lib/kamal/configuration/env.rb +10 -17
  48. data/lib/kamal/configuration/proxy.rb +66 -0
  49. data/lib/kamal/configuration/registry.rb +3 -2
  50. data/lib/kamal/configuration/role.rb +63 -94
  51. data/lib/kamal/configuration/validator/builder.rb +2 -0
  52. data/lib/kamal/configuration/validator/proxy.rb +11 -0
  53. data/lib/kamal/configuration/validator.rb +3 -1
  54. data/lib/kamal/configuration.rb +90 -33
  55. data/lib/kamal/env_file.rb +4 -0
  56. data/lib/kamal/secrets/adapters/base.rb +18 -0
  57. data/lib/kamal/secrets/adapters/bitwarden.rb +64 -0
  58. data/lib/kamal/secrets/adapters/last_pass.rb +30 -0
  59. data/lib/kamal/secrets/adapters/one_password.rb +61 -0
  60. data/lib/kamal/secrets/adapters/test.rb +10 -0
  61. data/lib/kamal/secrets/adapters.rb +14 -0
  62. data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +32 -0
  63. data/lib/kamal/secrets.rb +37 -0
  64. data/lib/kamal/sshkit_with_ext.rb +1 -0
  65. data/lib/kamal/utils.rb +12 -0
  66. data/lib/kamal/version.rb +1 -1
  67. data/lib/kamal.rb +3 -1
  68. metadata +23 -16
  69. data/lib/kamal/cli/env.rb +0 -54
  70. data/lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample +0 -3
  71. data/lib/kamal/cli/templates/template.env +0 -2
  72. data/lib/kamal/cli/traefik.rb +0 -122
  73. data/lib/kamal/commands/app/cord.rb +0 -22
  74. data/lib/kamal/commands/traefik.rb +0 -85
  75. data/lib/kamal/configuration/docs/healthcheck.yml +0 -59
  76. data/lib/kamal/configuration/docs/traefik.yml +0 -62
  77. data/lib/kamal/configuration/healthcheck.rb +0 -63
  78. data/lib/kamal/configuration/traefik.rb +0 -60
  79. /data/lib/kamal/cli/templates/sample_hooks/{pre-traefik-reboot.sample → pre-proxy-reboot.sample} +0 -0
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kamal
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.alpha
4
+ version: 2.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-01 00:00:00.000000000 Z
11
+ date: 2024-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -78,14 +78,14 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '2.8'
81
+ version: '3.1'
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '2.8'
88
+ version: '3.1'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: zeitwerk
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -218,25 +218,25 @@ files:
218
218
  - lib/kamal/cli/base.rb
219
219
  - lib/kamal/cli/build.rb
220
220
  - lib/kamal/cli/build/clone.rb
221
- - lib/kamal/cli/env.rb
222
221
  - lib/kamal/cli/healthcheck/barrier.rb
223
222
  - lib/kamal/cli/healthcheck/error.rb
224
223
  - lib/kamal/cli/healthcheck/poller.rb
225
224
  - lib/kamal/cli/lock.rb
226
225
  - lib/kamal/cli/main.rb
226
+ - lib/kamal/cli/proxy.rb
227
227
  - lib/kamal/cli/prune.rb
228
228
  - lib/kamal/cli/registry.rb
229
+ - lib/kamal/cli/secrets.rb
229
230
  - lib/kamal/cli/server.rb
230
231
  - lib/kamal/cli/templates/deploy.yml
231
232
  - lib/kamal/cli/templates/sample_hooks/docker-setup.sample
232
233
  - lib/kamal/cli/templates/sample_hooks/post-deploy.sample
233
- - lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample
234
+ - lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample
234
235
  - lib/kamal/cli/templates/sample_hooks/pre-build.sample
235
236
  - lib/kamal/cli/templates/sample_hooks/pre-connect.sample
236
237
  - lib/kamal/cli/templates/sample_hooks/pre-deploy.sample
237
- - lib/kamal/cli/templates/sample_hooks/pre-traefik-reboot.sample
238
- - lib/kamal/cli/templates/template.env
239
- - lib/kamal/cli/traefik.rb
238
+ - lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample
239
+ - lib/kamal/cli/templates/secrets
240
240
  - lib/kamal/commander.rb
241
241
  - lib/kamal/commander/specifics.rb
242
242
  - lib/kamal/commands.rb
@@ -244,10 +244,10 @@ files:
244
244
  - lib/kamal/commands/app.rb
245
245
  - lib/kamal/commands/app/assets.rb
246
246
  - lib/kamal/commands/app/containers.rb
247
- - lib/kamal/commands/app/cord.rb
248
247
  - lib/kamal/commands/app/execution.rb
249
248
  - lib/kamal/commands/app/images.rb
250
249
  - lib/kamal/commands/app/logging.rb
250
+ - lib/kamal/commands/app/proxy.rb
251
251
  - lib/kamal/commands/auditor.rb
252
252
  - lib/kamal/commands/base.rb
253
253
  - lib/kamal/commands/builder.rb
@@ -259,10 +259,10 @@ files:
259
259
  - lib/kamal/commands/docker.rb
260
260
  - lib/kamal/commands/hook.rb
261
261
  - lib/kamal/commands/lock.rb
262
+ - lib/kamal/commands/proxy.rb
262
263
  - lib/kamal/commands/prune.rb
263
264
  - lib/kamal/commands/registry.rb
264
265
  - lib/kamal/commands/server.rb
265
- - lib/kamal/commands/traefik.rb
266
266
  - lib/kamal/configuration.rb
267
267
  - lib/kamal/configuration/accessory.rb
268
268
  - lib/kamal/configuration/alias.rb
@@ -274,24 +274,22 @@ files:
274
274
  - lib/kamal/configuration/docs/builder.yml
275
275
  - lib/kamal/configuration/docs/configuration.yml
276
276
  - lib/kamal/configuration/docs/env.yml
277
- - lib/kamal/configuration/docs/healthcheck.yml
278
277
  - lib/kamal/configuration/docs/logging.yml
278
+ - lib/kamal/configuration/docs/proxy.yml
279
279
  - lib/kamal/configuration/docs/registry.yml
280
280
  - lib/kamal/configuration/docs/role.yml
281
281
  - lib/kamal/configuration/docs/servers.yml
282
282
  - lib/kamal/configuration/docs/ssh.yml
283
283
  - lib/kamal/configuration/docs/sshkit.yml
284
- - lib/kamal/configuration/docs/traefik.yml
285
284
  - lib/kamal/configuration/env.rb
286
285
  - lib/kamal/configuration/env/tag.rb
287
- - lib/kamal/configuration/healthcheck.rb
288
286
  - lib/kamal/configuration/logging.rb
287
+ - lib/kamal/configuration/proxy.rb
289
288
  - lib/kamal/configuration/registry.rb
290
289
  - lib/kamal/configuration/role.rb
291
290
  - lib/kamal/configuration/servers.rb
292
291
  - lib/kamal/configuration/ssh.rb
293
292
  - lib/kamal/configuration/sshkit.rb
294
- - lib/kamal/configuration/traefik.rb
295
293
  - lib/kamal/configuration/validation.rb
296
294
  - lib/kamal/configuration/validator.rb
297
295
  - lib/kamal/configuration/validator/accessory.rb
@@ -299,12 +297,21 @@ files:
299
297
  - lib/kamal/configuration/validator/builder.rb
300
298
  - lib/kamal/configuration/validator/configuration.rb
301
299
  - lib/kamal/configuration/validator/env.rb
300
+ - lib/kamal/configuration/validator/proxy.rb
302
301
  - lib/kamal/configuration/validator/registry.rb
303
302
  - lib/kamal/configuration/validator/role.rb
304
303
  - lib/kamal/configuration/validator/servers.rb
305
304
  - lib/kamal/configuration/volume.rb
306
305
  - lib/kamal/env_file.rb
307
306
  - lib/kamal/git.rb
307
+ - lib/kamal/secrets.rb
308
+ - lib/kamal/secrets/adapters.rb
309
+ - lib/kamal/secrets/adapters/base.rb
310
+ - lib/kamal/secrets/adapters/bitwarden.rb
311
+ - lib/kamal/secrets/adapters/last_pass.rb
312
+ - lib/kamal/secrets/adapters/one_password.rb
313
+ - lib/kamal/secrets/adapters/test.rb
314
+ - lib/kamal/secrets/dotenv/inline_command_substitution.rb
308
315
  - lib/kamal/sshkit_with_ext.rb
309
316
  - lib/kamal/tags.rb
310
317
  - lib/kamal/utils.rb
@@ -329,7 +336,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
329
336
  - !ruby/object:Gem::Version
330
337
  version: '0'
331
338
  requirements: []
332
- rubygems_version: 3.5.17
339
+ rubygems_version: 3.5.16
333
340
  signing_key:
334
341
  specification_version: 4
335
342
  summary: Deploy web apps in containers to servers running Docker with zero downtime.
data/lib/kamal/cli/env.rb DELETED
@@ -1,54 +0,0 @@
1
- require "tempfile"
2
-
3
- class Kamal::Cli::Env < Kamal::Cli::Base
4
- desc "push", "Push the env file to the remote hosts"
5
- def push
6
- with_lock do
7
- on(KAMAL.hosts) do
8
- execute *KAMAL.auditor.record("Pushed env files"), verbosity: :debug
9
-
10
- KAMAL.roles_on(host).each do |role|
11
- execute *KAMAL.app(role: role, host: host).make_env_directory
12
- upload! role.env(host).secrets_io, role.env(host).secrets_file, mode: 400
13
- end
14
- end
15
-
16
- on(KAMAL.traefik_hosts) do
17
- execute *KAMAL.traefik.make_env_directory
18
- upload! KAMAL.traefik.env.secrets_io, KAMAL.traefik.env.secrets_file, mode: 400
19
- end
20
-
21
- on(KAMAL.accessory_hosts) do
22
- KAMAL.accessories_on(host).each do |accessory|
23
- accessory_config = KAMAL.config.accessory(accessory)
24
- execute *KAMAL.accessory(accessory).make_env_directory
25
- upload! accessory_config.env.secrets_io, accessory_config.env.secrets_file, mode: 400
26
- end
27
- end
28
- end
29
- end
30
-
31
- desc "delete", "Delete the env file from the remote hosts"
32
- def delete
33
- with_lock do
34
- on(KAMAL.hosts) do
35
- execute *KAMAL.auditor.record("Deleted env files"), verbosity: :debug
36
-
37
- KAMAL.roles_on(host).each do |role|
38
- execute *KAMAL.app(role: role, host: host).remove_env_file
39
- end
40
- end
41
-
42
- on(KAMAL.traefik_hosts) do
43
- execute *KAMAL.traefik.remove_env_file
44
- end
45
-
46
- on(KAMAL.accessory_hosts) do
47
- KAMAL.accessories_on(host).each do |accessory|
48
- accessory_config = KAMAL.config.accessory(accessory)
49
- execute *KAMAL.accessory(accessory).remove_env_file
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,3 +0,0 @@
1
- #!/bin/sh
2
-
3
- echo "Rebooted Traefik on $KAMAL_HOSTS"
@@ -1,2 +0,0 @@
1
- KAMAL_REGISTRY_PASSWORD=change-this
2
- RAILS_MASTER_KEY=another-env
@@ -1,122 +0,0 @@
1
- class Kamal::Cli::Traefik < Kamal::Cli::Base
2
- desc "boot", "Boot Traefik on servers"
3
- def boot
4
- with_lock do
5
- on(KAMAL.traefik_hosts) do
6
- execute *KAMAL.registry.login
7
- execute *KAMAL.traefik.start_or_run
8
- end
9
- end
10
- end
11
-
12
- desc "reboot", "Reboot Traefik on servers (stop container, remove container, start new container)"
13
- option :rolling, type: :boolean, default: false, desc: "Reboot traefik on hosts in sequence, rather than in parallel"
14
- option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
15
- def reboot
16
- confirming "This will cause a brief outage on each host. Are you sure?" do
17
- with_lock do
18
- host_groups = options[:rolling] ? KAMAL.traefik_hosts : [ KAMAL.traefik_hosts ]
19
- host_groups.each do |hosts|
20
- host_list = Array(hosts).join(",")
21
- run_hook "pre-traefik-reboot", hosts: host_list
22
- on(hosts) do
23
- execute *KAMAL.auditor.record("Rebooted traefik"), verbosity: :debug
24
- execute *KAMAL.registry.login
25
- execute *KAMAL.traefik.stop, raise_on_non_zero_exit: false
26
- execute *KAMAL.traefik.remove_container
27
- execute *KAMAL.traefik.run
28
- end
29
- run_hook "post-traefik-reboot", hosts: host_list
30
- end
31
- end
32
- end
33
- end
34
-
35
- desc "start", "Start existing Traefik container on servers"
36
- def start
37
- with_lock do
38
- on(KAMAL.traefik_hosts) do
39
- execute *KAMAL.auditor.record("Started traefik"), verbosity: :debug
40
- execute *KAMAL.traefik.start
41
- end
42
- end
43
- end
44
-
45
- desc "stop", "Stop existing Traefik container on servers"
46
- def stop
47
- with_lock do
48
- on(KAMAL.traefik_hosts) do
49
- execute *KAMAL.auditor.record("Stopped traefik"), verbosity: :debug
50
- execute *KAMAL.traefik.stop, raise_on_non_zero_exit: false
51
- end
52
- end
53
- end
54
-
55
- desc "restart", "Restart existing Traefik container on servers"
56
- def restart
57
- with_lock do
58
- stop
59
- start
60
- end
61
- end
62
-
63
- desc "details", "Show details about Traefik container from servers"
64
- def details
65
- on(KAMAL.traefik_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.traefik.info), type: "Traefik" }
66
- end
67
-
68
- desc "logs", "Show log lines from Traefik on servers"
69
- option :since, aliases: "-s", desc: "Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)"
70
- option :lines, type: :numeric, aliases: "-n", desc: "Number of log lines to pull from each server"
71
- option :grep, aliases: "-g", desc: "Show lines with grep match only (use this to fetch specific requests by id)"
72
- option :grep_options, aliases: "-o", desc: "Additional options supplied to grep"
73
- option :follow, aliases: "-f", desc: "Follow logs on primary server (or specific host set by --hosts)"
74
- def logs
75
- grep = options[:grep]
76
- grep_options = options[:grep_options]
77
-
78
- if options[:follow]
79
- run_locally do
80
- info "Following logs on #{KAMAL.primary_host}..."
81
- info KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep, grep_options: grep_options)
82
- exec KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep, grep_options: grep_options)
83
- end
84
- else
85
- since = options[:since]
86
- lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
87
-
88
- on(KAMAL.traefik_hosts) do |host|
89
- puts_by_host host, capture(*KAMAL.traefik.logs(since: since, lines: lines, grep: grep, grep_options: grep_options)), type: "Traefik"
90
- end
91
- end
92
- end
93
-
94
- desc "remove", "Remove Traefik container and image from servers"
95
- def remove
96
- with_lock do
97
- stop
98
- remove_container
99
- remove_image
100
- end
101
- end
102
-
103
- desc "remove_container", "Remove Traefik container from servers", hide: true
104
- def remove_container
105
- with_lock do
106
- on(KAMAL.traefik_hosts) do
107
- execute *KAMAL.auditor.record("Removed traefik container"), verbosity: :debug
108
- execute *KAMAL.traefik.remove_container
109
- end
110
- end
111
- end
112
-
113
- desc "remove_image", "Remove Traefik image from servers", hide: true
114
- def remove_image
115
- with_lock do
116
- on(KAMAL.traefik_hosts) do
117
- execute *KAMAL.auditor.record("Removed traefik image"), verbosity: :debug
118
- execute *KAMAL.traefik.remove_image
119
- end
120
- end
121
- end
122
- end
@@ -1,22 +0,0 @@
1
- module Kamal::Commands::App::Cord
2
- def cord(version:)
3
- pipe \
4
- docker(:inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", container_name(version)),
5
- [ :awk, "'$2 == \"#{role.cord_volume.container_path}\" {print $1}'" ]
6
- end
7
-
8
- def tie_cord(cord)
9
- create_empty_file(cord)
10
- end
11
-
12
- def cut_cord(cord)
13
- remove_directory(cord)
14
- end
15
-
16
- private
17
- def create_empty_file(file)
18
- chain \
19
- make_directory_for(file),
20
- [ :touch, file ]
21
- end
22
- end
@@ -1,85 +0,0 @@
1
- class Kamal::Commands::Traefik < Kamal::Commands::Base
2
- delegate :argumentize, :optionize, to: Kamal::Utils
3
- delegate :port, :publish?, :labels, :env, :image, :options, :args, to: :"config.traefik"
4
-
5
- def run
6
- docker :run, "--name traefik",
7
- "--detach",
8
- "--restart", "unless-stopped",
9
- *publish_args,
10
- "--volume", "/var/run/docker.sock:/var/run/docker.sock",
11
- *env_args,
12
- *config.logging_args,
13
- *label_args,
14
- *docker_options_args,
15
- image,
16
- "--providers.docker",
17
- *cmd_option_args
18
- end
19
-
20
- def start
21
- docker :container, :start, "traefik"
22
- end
23
-
24
- def stop
25
- docker :container, :stop, "traefik"
26
- end
27
-
28
- def start_or_run
29
- any start, run
30
- end
31
-
32
- def info
33
- docker :ps, "--filter", "name=^traefik$"
34
- end
35
-
36
- def logs(since: nil, lines: nil, grep: nil, grep_options: nil)
37
- pipe \
38
- docker(:logs, "traefik", (" --since #{since}" if since), (" --tail #{lines}" if lines), "--timestamps", "2>&1"),
39
- ("grep '#{grep}'#{" #{grep_options}" if grep_options}" if grep)
40
- end
41
-
42
- def follow_logs(host:, grep: nil, grep_options: nil)
43
- run_over_ssh pipe(
44
- docker(:logs, "traefik", "--timestamps", "--tail", "10", "--follow", "2>&1"),
45
- (%(grep "#{grep}"#{" #{grep_options}" if grep_options}) if grep)
46
- ).join(" "), host: host
47
- end
48
-
49
- def remove_container
50
- docker :container, :prune, "--force", "--filter", "label=org.opencontainers.image.title=Traefik"
51
- end
52
-
53
- def remove_image
54
- docker :image, :prune, "--all", "--force", "--filter", "label=org.opencontainers.image.title=Traefik"
55
- end
56
-
57
- def make_env_directory
58
- make_directory(env.secrets_directory)
59
- end
60
-
61
- def remove_env_file
62
- [ :rm, "-f", env.secrets_file ]
63
- end
64
-
65
- private
66
- def publish_args
67
- argumentize "--publish", port if publish?
68
- end
69
-
70
- def label_args
71
- argumentize "--label", labels
72
- end
73
-
74
- def env_args
75
- env.args
76
- end
77
-
78
- def docker_options_args
79
- optionize(options)
80
- end
81
-
82
- def cmd_option_args
83
- optionize args, with: "="
84
- end
85
- end
@@ -1,59 +0,0 @@
1
- # Healthcheck configuration
2
- #
3
- # On roles that are running Traefik, Kamal will supply a default healthcheck to `docker run`.
4
- # For other roles, by default no healthcheck is supplied.
5
- #
6
- # If no healthcheck is supplied and the image does not define one, they we wait for the container
7
- # to reach a running state and then pause for the readiness delay.
8
- #
9
- # The default healthcheck is `curl -f http://localhost:<port>/<path>`, so it assumes that `curl`
10
- # is available within the container.
11
-
12
- # Healthcheck options
13
- #
14
- # These go under the `healthcheck` key in the root or role configuration.
15
- healthcheck:
16
-
17
- # Command
18
- #
19
- # The command to run, defaults to `curl -f http://localhost:<port>/<path>` on roles running Traefik
20
- cmd: "curl -f http://localhost"
21
-
22
- # Interval
23
- #
24
- # The Docker healthcheck interval, defaults to `1s`
25
- interval: 10s
26
-
27
- # Max attempts
28
- #
29
- # The maximum number of times we poll the container to see if it is healthy, defaults to `7`
30
- # Each check is separated by an increasing interval starting with 1 second.
31
- max_attempts: 3
32
-
33
- # Port
34
- #
35
- # The port to use in the healthcheck, defaults to `3000`
36
- port: "80"
37
-
38
- # Path
39
- #
40
- # The path to use in the healthcheck, defaults to `/up`
41
- path: /health
42
-
43
- # Cords for zero-downtime deployments
44
- #
45
- # The cord file is used for zero-downtime deployments. The healthcheck is augmented with a check
46
- # for the existance of the file. This allows us to delete the file and force the container to
47
- # become unhealthy, causing Traefik to stop routing traffic to it.
48
- #
49
- # Kamal mounts a volume at this location and creates the file before starting the container.
50
- # You can set the value to `false` to disable the cord file, but this loses the zero-downtime
51
- # guarantee.
52
- #
53
- # The default value is `/tmp/kamal-cord`
54
- cord: /cord
55
-
56
- # Log lines
57
- #
58
- # Number of lines to log from the container when the healthcheck fails, defaults to `50`
59
- log_lines: 100
@@ -1,62 +0,0 @@
1
- # Traefik
2
- #
3
- # Traefik is a reverse proxy, used by Kamal for zero-downtime deployments.
4
- #
5
- # We start an instance on the hosts in it's own container.
6
- #
7
- # During a deployment:
8
- # 1. We start a new container which Traefik automatically detects due to the labels we have applied
9
- # 2. Traefik starts routing traffic to the new container
10
- # 3. We force the old container to fail it's healthcheck, causing Traefik to stop routing traffic to it
11
- # 4. We stop the old container
12
-
13
- # Traefik settings
14
- #
15
- # Traekik is configured in the root configuration under `traefik`.
16
- traefik:
17
-
18
- # Image
19
- #
20
- # The Traefik image to use, defaults to `traefik:v2.10`
21
- image: traefik:v2.9
22
-
23
- # Host port
24
- #
25
- # The host port to publish the Traefik container on, defaults to `80`
26
- host_port: "8080"
27
-
28
- # Disabling publishing
29
- #
30
- # To avoid publishing the Traefik container, set this to `false`
31
- publish: false
32
-
33
- # Labels
34
- #
35
- # Additional labels to apply to the Traefik container
36
- labels:
37
- traefik.http.routers.catchall.entryPoints: http
38
- traefik.http.routers.catchall.rule: PathPrefix(`/`)
39
- traefik.http.routers.catchall.service: unavailable
40
- traefik.http.routers.catchall.priority: "1"
41
- traefik.http.services.unavailable.loadbalancer.server.port: "0"
42
-
43
- # Arguments
44
- #
45
- # Additional arguments to pass to the Traefik container
46
- args:
47
- entryPoints.http.address: ":80"
48
- entryPoints.http.forwardedHeaders.insecure: true
49
- accesslog: true
50
- accesslog.format: json
51
-
52
- # Options
53
- #
54
- # Additional options to pass to `docker run`
55
- options:
56
- cpus: 2
57
-
58
- # Environment variables
59
- #
60
- # See kamal docs env
61
- env:
62
- ...
@@ -1,63 +0,0 @@
1
- class Kamal::Configuration::Healthcheck
2
- include Kamal::Configuration::Validation
3
-
4
- attr_reader :healthcheck_config
5
-
6
- def initialize(healthcheck_config:, context: "healthcheck")
7
- @healthcheck_config = healthcheck_config || {}
8
- validate! @healthcheck_config, context: context
9
- end
10
-
11
- def merge(other)
12
- self.class.new healthcheck_config: healthcheck_config.deep_merge(other.healthcheck_config)
13
- end
14
-
15
- def cmd
16
- healthcheck_config.fetch("cmd", http_health_check)
17
- end
18
-
19
- def port
20
- healthcheck_config.fetch("port", 3000)
21
- end
22
-
23
- def path
24
- healthcheck_config.fetch("path", "/up")
25
- end
26
-
27
- def max_attempts
28
- healthcheck_config.fetch("max_attempts", 7)
29
- end
30
-
31
- def interval
32
- healthcheck_config.fetch("interval", "1s")
33
- end
34
-
35
- def cord
36
- healthcheck_config.fetch("cord", "/tmp/kamal-cord")
37
- end
38
-
39
- def log_lines
40
- healthcheck_config.fetch("log_lines", 50)
41
- end
42
-
43
- def set_port_or_path?
44
- healthcheck_config["port"].present? || healthcheck_config["path"].present?
45
- end
46
-
47
- def to_h
48
- {
49
- "cmd" => cmd,
50
- "interval" => interval,
51
- "max_attempts" => max_attempts,
52
- "port" => port,
53
- "path" => path,
54
- "cord" => cord,
55
- "log_lines" => log_lines
56
- }
57
- end
58
-
59
- private
60
- def http_health_check
61
- "curl -f #{URI.join("http://localhost:#{port}", path)} || exit 1" if path.present? || port.present?
62
- end
63
- end
@@ -1,60 +0,0 @@
1
- class Kamal::Configuration::Traefik
2
- DEFAULT_IMAGE = "traefik:v2.10"
3
- CONTAINER_PORT = 80
4
- DEFAULT_ARGS = {
5
- "log.level" => "DEBUG"
6
- }
7
- DEFAULT_LABELS = {
8
- # These ensure we serve a 502 rather than a 404 if no containers are available
9
- "traefik.http.routers.catchall.entryPoints" => "http",
10
- "traefik.http.routers.catchall.rule" => "PathPrefix(`/`)",
11
- "traefik.http.routers.catchall.service" => "unavailable",
12
- "traefik.http.routers.catchall.priority" => 1,
13
- "traefik.http.services.unavailable.loadbalancer.server.port" => "0"
14
- }
15
-
16
- include Kamal::Configuration::Validation
17
-
18
- attr_reader :config, :traefik_config
19
-
20
- def initialize(config:)
21
- @config = config
22
- @traefik_config = config.raw_config.traefik || {}
23
- validate! traefik_config
24
- end
25
-
26
- def publish?
27
- traefik_config["publish"] != false
28
- end
29
-
30
- def labels
31
- DEFAULT_LABELS.merge(traefik_config["labels"] || {})
32
- end
33
-
34
- def env
35
- Kamal::Configuration::Env.new \
36
- config: traefik_config.fetch("env", {}),
37
- secrets_file: File.join(config.host_env_directory, "traefik", "traefik.env"),
38
- context: "traefik/env"
39
- end
40
-
41
- def host_port
42
- traefik_config.fetch("host_port", CONTAINER_PORT)
43
- end
44
-
45
- def options
46
- traefik_config.fetch("options", {})
47
- end
48
-
49
- def port
50
- "#{host_port}:#{CONTAINER_PORT}"
51
- end
52
-
53
- def args
54
- DEFAULT_ARGS.merge(traefik_config.fetch("args", {}))
55
- end
56
-
57
- def image
58
- traefik_config.fetch("image", DEFAULT_IMAGE)
59
- end
60
- end