Copy env files to remote hosts

Setting env variables in the docker arguments requires having them on
the deploy host.

Instead we'll add two new commands `kamal env push` and
`kamal env delete` which will manage copying the environment as .env
files to the remote host.

Docker will pick up the file with `--env-file <path-to-file>`. Env files
will be stored under `<kamal run directory>/env`.

Running `kamal env push` will create env files for each role and
accessory, and traefik if required.

`kamal envify` has been updated to also push the env files.

By avoiding using `kamal envify` and creating the local and remote
secrets manually, you can now avoid accessing secrets needed
for the docker runtime environment locally. You will still need build
secrets.

One thing to note - the Docker doesn't parse the environment variables
in the env file, one result of this is that you can't specify multi-line
values - see https://github.com/moby/moby/issues/12997.

We maybe need to look docker config or docker secrets longer term to get
around this.

Hattip to @kevinmcconnell - this was all his idea.
This commit is contained in:
Donal McBreen
2023-08-30 15:16:48 +01:00
parent adc7173cf2
commit 94bf090657
32 changed files with 453 additions and 170 deletions

View File

@@ -86,14 +86,6 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
end
end
def make_directory_for(remote_file)
make_directory Pathname.new(remote_file).dirname.to_s
end
def make_directory(path)
[ :mkdir, "-p", path ]
end
def remove_service_directory
[ :rm, "-rf", service_name ]
end
@@ -106,6 +98,14 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
docker :image, :rm, "--force", image
end
def make_env_directory
make_directory accessory_config.host_env_directory
end
def remove_env_file
[:rm, "-f", accessory_config.host_env_file_path]
end
private
def service_filter
[ "--filter", "label=service=#{service_name}" ]

View File

@@ -81,7 +81,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
docker :run,
("-it" if interactive),
"--rm",
*config.env_args,
*role&.env_args,
*config.volume_args,
*role&.option_args,
config.absolute_image,
@@ -149,6 +149,13 @@ class Kamal::Commands::App < Kamal::Commands::Base
docker :tag, config.absolute_image, config.latest_image
end
def make_env_directory
make_directory config.role(role).host_env_directory
end
def remove_env_file
[:rm, "-f", config.role(role).host_env_file_path]
end
private
def container_name(version = nil)

View File

@@ -26,6 +26,14 @@ module Kamal::Commands
docker :container, :ls, *("--all" unless only_running), "--filter", "name=^#{container_name}$", "--quiet"
end
def make_directory_for(remote_file)
make_directory Pathname.new(remote_file).dirname.to_s
end
def make_directory(path)
[ :mkdir, "-p", path ]
end
private
def combine(*commands, by: "&&")
commands

View File

@@ -1,5 +1,5 @@
class Kamal::Commands::Traefik < Kamal::Commands::Base
delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Kamal::Utils
delegate :argumentize, :env_file_with_secrets, :optionize, to: Kamal::Utils
DEFAULT_IMAGE = "traefik:v2.9"
CONTAINER_PORT = 80
@@ -63,6 +63,22 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
"#{host_port}:#{CONTAINER_PORT}"
end
def env_file
env_file_with_secrets config.traefik.fetch("env", {})
end
def host_env_file_path
File.join host_env_directory, "traefik.env"
end
def make_env_directory
make_directory(host_env_directory)
end
def remove_env_file
[:rm, "-f", host_env_file_path]
end
private
def publish_args
argumentize "--publish", port unless config.traefik["publish"] == false
@@ -73,13 +89,11 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
end
def env_args
env_config = config.traefik["env"] || {}
argumentize "--env-file", host_env_file_path
end
if env_config.present?
argumentize_env_with_secrets(env_config)
else
[]
end
def host_env_directory
File.join config.host_env_directory, "traefik"
end
def labels