From 63ebeda4897db28b3e53be8b607d31856520af21 Mon Sep 17 00:00:00 2001 From: Donal McBreen Date: Thu, 5 Sep 2024 14:31:37 +0100 Subject: [PATCH] Create proxy and app containers in a kamal network --- lib/kamal/cli/proxy.rb | 6 ++++++ lib/kamal/commands/app.rb | 7 +++---- lib/kamal/commands/app/containers.rb | 2 +- lib/kamal/commands/docker.rb | 4 ++++ lib/kamal/commands/proxy.rb | 1 + test/cli/app_test.rb | 2 +- test/cli/proxy_test.rb | 8 ++++---- test/commands/proxy_test.rb | 8 ++++---- 8 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/kamal/cli/proxy.rb b/lib/kamal/cli/proxy.rb index d546439c..87fee4b4 100644 --- a/lib/kamal/cli/proxy.rb +++ b/lib/kamal/cli/proxy.rb @@ -3,6 +3,12 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base def boot raise_unless_kamal_proxy_enabled! with_lock do + on(KAMAL.hosts) do |host| + execute *KAMAL.docker.create_network + rescue SSHKit::Command::Failed => e + raise unless e.message.include?("already exists") + end + on(KAMAL.traefik_hosts) do |host| execute *KAMAL.registry.login execute *KAMAL.traefik_or_proxy(host).start_or_run diff --git a/lib/kamal/commands/app.rb b/lib/kamal/commands/app.rb index ad6e0613..94ef29e9 100644 --- a/lib/kamal/commands/app.rb +++ b/lib/kamal/commands/app.rb @@ -5,6 +5,8 @@ class Kamal::Commands::App < Kamal::Commands::Base attr_reader :role, :host + delegate :container_name, to: :role + def initialize(config, role: nil, host: nil) super(config) @role = role @@ -35,6 +37,7 @@ class Kamal::Commands::App < Kamal::Commands::Base "--detach", "--restart unless-stopped", "--name", container_name, + "--network", "kamal", *([ "--hostname", hostname ] if hostname), "-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"", "-e", "KAMAL_VERSION=\"#{config.version}\"", @@ -92,10 +95,6 @@ class Kamal::Commands::App < Kamal::Commands::Base end private - def container_name(version = nil) - [ role.container_prefix, version || config.version ].compact.join("-") - end - def latest_image_id docker :image, :ls, *argumentize("--filter", "reference=#{config.latest_image}"), "--format", "'{{.ID}}'" end diff --git a/lib/kamal/commands/app/containers.rb b/lib/kamal/commands/app/containers.rb index 629fa47f..2d828962 100644 --- a/lib/kamal/commands/app/containers.rb +++ b/lib/kamal/commands/app/containers.rb @@ -32,7 +32,7 @@ module Kamal::Commands::App::Containers def container_endpoint(version:) pipe \ container_id_for(container_name: container_name(version)), - xargs(docker(:inspect, "--format", "'{{.NetworkSettings.IPAddress}}{{range $k, $v := .NetworkSettings.Ports}}{{printf \":%s\" $k}}{{break}}{{end}}'")), + xargs(docker(:inspect, "--format", "'{{index .NetworkSettings.Networks.kamal.Aliases 0}}{{range $k, $v := .NetworkSettings.Ports}}{{printf \":%s\" $k}}{{break}}{{end}}'")), [ :sed, "-e", "'s/\\/tcp$//'" ] end end diff --git a/lib/kamal/commands/docker.rb b/lib/kamal/commands/docker.rb index 2966e095..bc9345df 100644 --- a/lib/kamal/commands/docker.rb +++ b/lib/kamal/commands/docker.rb @@ -19,6 +19,10 @@ class Kamal::Commands::Docker < Kamal::Commands::Base [ '[ "${EUID:-$(id -u)}" -eq 0 ] || command -v sudo >/dev/null || command -v su >/dev/null' ] end + def create_network + docker :network, :create, :kamal + end + private def get_docker shell \ diff --git a/lib/kamal/commands/proxy.rb b/lib/kamal/commands/proxy.rb index 9ae029f7..3a17afae 100644 --- a/lib/kamal/commands/proxy.rb +++ b/lib/kamal/commands/proxy.rb @@ -12,6 +12,7 @@ class Kamal::Commands::Proxy < Kamal::Commands::Base def run docker :run, "--name", container_name, + "--network", "kamal", "--detach", "--restart", "unless-stopped", *proxy_config.publish_args, diff --git a/test/cli/app_test.rb b/test/cli/app_test.rb index 81ac8b16..225bf21d 100644 --- a/test/cli/app_test.rb +++ b/test/cli/app_test.rb @@ -362,7 +362,7 @@ class CliAppTest < CliTestCase run_command("boot", config: :with_proxy).tap do |output| assert_match /Renaming container .* to .* as already deployed on 1.1.1.1/, output # Rename assert_match /docker rename app-web-latest app-web-latest_replaced_[0-9a-f]{16}/, output - assert_match /docker run --detach --restart unless-stopped --name app-web-latest --hostname 1.1.1.1-[0-9a-f]{12} -e KAMAL_CONTAINER_NAME="app-web-latest" -e KAMAL_VERSION="latest" --env-file .kamal\/env\/roles\/app-web.env --log-opt max-size="10m" --label service="app" --label role="web" --label destination dhh\/app:latest/, output + assert_match /docker run --detach --restart unless-stopped --name app-web-latest --network kamal --hostname 1.1.1.1-[0-9a-f]{12} -e KAMAL_CONTAINER_NAME="app-web-latest" -e KAMAL_VERSION="latest" --env-file .kamal\/env\/roles\/app-web.env --log-opt max-size="10m" --label service="app" --label role="web" --label destination dhh\/app:latest/, output assert_match /docker exec kamal-proxy kamal-proxy deploy app-web --target "123"/, output assert_match "docker container ls --all --filter name=^app-web-123$ --quiet | xargs docker stop", output end diff --git a/test/cli/proxy_test.rb b/test/cli/proxy_test.rb index 92ab3003..e35c3c06 100644 --- a/test/cli/proxy_test.rb +++ b/test/cli/proxy_test.rb @@ -4,13 +4,13 @@ class CliProxyTest < CliTestCase test "boot" do run_command("boot").tap do |output| assert_match "docker login", output - assert_match "docker run --name kamal-proxy --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", output + assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", output end end test "reboot" do SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) - .with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-123$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{.NetworkSettings.IPAddress}}{{range $k, $v := .NetworkSettings.Ports}}{{printf \":%s\" $k}}{{break}}{{end}}'", "|", :sed, "-e", "'s/\\/tcp$//'") + .with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-123$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{index .NetworkSettings.Networks.kamal.Aliases 0}}{{range $k, $v := .NetworkSettings.Ports}}{{printf \":%s\" $k}}{{break}}{{end}}'", "|", :sed, "-e", "'s/\\/tcp$//'") .returns("172.1.0.2:80") .at_least_once @@ -24,7 +24,7 @@ class CliProxyTest < CliTestCase assert_match "docker container stop traefik on 1.1.1.1", output assert_match "docker container prune --force --filter label=org.opencontainers.image.title=kamal-proxy on 1.1.1.1", output assert_match "docker container prune --force --filter label=org.opencontainers.image.title=Traefik on 1.1.1.1", output - assert_match "docker run --name kamal-proxy --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE} on 1.1.1.1", output + assert_match "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE} on 1.1.1.1", output assert_match "docker exec kamal-proxy kamal-proxy deploy app-web --target \"172.1.0.2:80\" --deploy-timeout \"6s\" --buffer-requests --buffer-responses --log-request-header \"Cache-Control\" --log-request-header \"Last-Modified\" on 1.1.1.1", output assert_match "docker container stop kamal-proxy on 1.1.1.2", output @@ -37,7 +37,7 @@ class CliProxyTest < CliTestCase test "reboot --rolling" do SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) - .with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-123$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{.NetworkSettings.IPAddress}}{{range $k, $v := .NetworkSettings.Ports}}{{printf \":%s\" $k}}{{break}}{{end}}'", "|", :sed, "-e", "'s/\\/tcp$//'") + .with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-123$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{index .NetworkSettings.Networks.kamal.Aliases 0}}{{range $k, $v := .NetworkSettings.Ports}}{{printf \":%s\" $k}}{{break}}{{end}}'", "|", :sed, "-e", "'s/\\/tcp$//'") .returns("172.1.0.2:80") .at_least_once diff --git a/test/commands/proxy_test.rb b/test/commands/proxy_test.rb index 7e7a60cb..0a2cc6c0 100644 --- a/test/commands/proxy_test.rb +++ b/test/commands/proxy_test.rb @@ -15,13 +15,13 @@ class CommandsProxyTest < ActiveSupport::TestCase test "run" do assert_equal \ - "docker run --name kamal-proxy --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end test "run with ports configured" do assert_equal \ - "docker run --name kamal-proxy --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end @@ -29,7 +29,7 @@ class CommandsProxyTest < ActiveSupport::TestCase @config.delete(:proxy) assert_equal \ - "docker run --name kamal-proxy --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-opt max-size=\"10m\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end @@ -37,7 +37,7 @@ class CommandsProxyTest < ActiveSupport::TestCase @config[:logging] = { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => "3" } } assert_equal \ - "docker run --name kamal-proxy --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", + "docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume kamal-proxy:/root/.config/kamal-proxy --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" #{Kamal::Configuration::Proxy::DEFAULT_IMAGE}", new_command.run.join(" ") end