diff --git a/README.md b/README.md index b0e54191..8deb7f54 100644 --- a/README.md +++ b/README.md @@ -450,9 +450,9 @@ RUN --mount=type=secret,id=GITHUB_TOKEN \ rm -rf /usr/local/bundle/cache ``` -### Using command arguments for Traefik +### Traefik command arguments -You can customize the traefik command line: +Customize the Traefik command line using `args`: ```yaml traefik: @@ -461,20 +461,38 @@ traefik: accesslog.format: json ``` -This will start the traefik container with `--accesslog=true accesslog.format=json`. +This starts the Traefik container with `--accesslog=true --accesslog.format=json` arguments. -### Traefik's host port binding +### Traefik host port binding -By default Traefik binds to port 80 of the host machine, it can be configured to use an alternative port: +Traefik binds to port 80 by default. Specify an alternative port using `host_port`: ```yaml traefik: host_port: 8080 ``` -### Configure docker options for traefik +### Traefik version, upgrades, and custom images -We allow users to pass additional docker options to the trafik container like +MRSK runs the traefik:v2.9 image to track Traefik 2.9.x releases. + +To pin Traefik to a specific version or an image published to your registry, +specify `image`: + +```yaml +traefik: + image: traefik:v2.10.0-rc1 +``` + +This is useful for downgrading Traefik if there's an unexpected breaking +change in a minor version release, upgrading Traefik to test forthcoming +releases, or running your own Traefik-derived image. + +MRSK has not been tested for compatibility with Traefik 3 betas. Please do! + +### Traefik container configuration + +Pass additional Docker configuration for the Traefik container using `options`: ```yaml traefik: @@ -486,12 +504,12 @@ traefik: memory: 512m ``` -This will start the traefik container with a command like: `docker run ... --volume /tmp/example.json:/tmp/example.json --publish 8080:8080 ` +This starts the Traefik container with `--volume /tmp/example.json:/tmp/example.json --publish 8080:8080 --memory 512m` arguments to `docker run`. -### Configure alternate entrypoints for traefik +### Traefik alternate entrypoints -You can configure multiple entrypoints for traefik like so: +You can configure multiple entrypoints for Traefik like so: ```yaml service: myservice diff --git a/lib/mrsk/cli/traefik.rb b/lib/mrsk/cli/traefik.rb index 7be64e8e..df70ab43 100644 --- a/lib/mrsk/cli/traefik.rb +++ b/lib/mrsk/cli/traefik.rb @@ -2,7 +2,10 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base desc "boot", "Boot Traefik on servers" def boot with_lock do - on(MRSK.traefik_hosts) { execute *MRSK.traefik.run, raise_on_non_zero_exit: false } + on(MRSK.traefik_hosts) do + execute *MRSK.registry.login + execute *MRSK.traefik.run, raise_on_non_zero_exit: false + end end end diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index 248a33ad..d6cc8ffc 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -1,7 +1,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base delegate :optionize, to: Mrsk::Utils - IMAGE = "traefik:v2.9.9" + DEFAULT_IMAGE = "traefik:v2.9" CONTAINER_PORT = 80 def run @@ -12,7 +12,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base "--volume", "/var/run/docker.sock:/var/run/docker.sock", *config.logging_args, *docker_options_args, - IMAGE, + image, "--providers.docker", "--log.level=DEBUG", *cmd_option_args @@ -56,6 +56,10 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base end private + def image + config.traefik.fetch("image") { DEFAULT_IMAGE } + end + def docker_options_args optionize(config.traefik["options"] || {}) end diff --git a/test/cli/traefik_test.rb b/test/cli/traefik_test.rb index e89fb62b..2cf2513a 100644 --- a/test/cli/traefik_test.rb +++ b/test/cli/traefik_test.rb @@ -3,7 +3,8 @@ require_relative "cli_test_case" class CliTraefikTest < CliTestCase test "boot" do run_command("boot").tap do |output| - assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG", output + assert_match "docker login", output + assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Mrsk::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=DEBUG", output end end diff --git a/test/commands/traefik_test.rb b/test/commands/traefik_test.rb index 680c1731..e6c6178c 100644 --- a/test/commands/traefik_test.rb +++ b/test/commands/traefik_test.rb @@ -2,53 +2,55 @@ require "test_helper" class CommandsTraefikTest < ActiveSupport::TestCase setup do + @image = "traefik:test" + @config = { service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" }, servers: [ "1.1.1.1" ], - traefik: { "args" => { "accesslog.format" => "json", "api.insecure" => true, "metrics.prometheus.buckets" => "0.1,0.3,1.2,5.0" } } + traefik: { "image" => @image, "args" => { "accesslog.format" => "json", "api.insecure" => true, "metrics.prometheus.buckets" => "0.1,0.3,1.2,5.0" } } } end test "run" do assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") @config[:traefik]["host_port"] = "8080" assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 8080:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 8080:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end test "run with ports configured" do assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") @config[:traefik]["options"] = {"publish" => %w[9000:9000 9001:9001]} assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" --publish \"9000:9000\" --publish \"9001:9001\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" --publish \"9000:9000\" --publish \"9001:9001\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end test "run with volumes configured" do assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") @config[:traefik]["options"] = {"volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json] } assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end test "run with several options configured" do assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") @config[:traefik]["options"] = {"volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json], "publish" => %w[8080:8080], "memory" => "512m"} assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" --publish \"8080:8080\" --memory \"512m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" --publish \"8080:8080\" --memory \"512m\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end @@ -56,7 +58,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase @config.delete(:traefik) assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" traefik:v2.9.9 --providers.docker --log.level=DEBUG", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Mrsk::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=DEBUG", new_command.run.join(" ") end @@ -64,7 +66,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase @config[:logging] = { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => "3" } } assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" traefik:v2.9.9 --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" #{@image} --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end