diff --git a/README.md b/README.md index 23fc8ad61..c70284a28 100644 --- a/README.md +++ b/README.md @@ -585,6 +585,22 @@ ARG RUBY_VERSION FROM ruby:$RUBY_VERSION-slim as base ``` +### Forward your existing SSH agent connection to docker + +Clone your private repositories during build. + +```yaml + builder: + ssh: $HOME/.ssh/name_of_your_ssh_key +``` + +Then, include the following in your Dockerfile: + +```dockerfile +RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts +RUN --mount=type=ssh bundle install +``` + ### Using accessories for database, cache, search services You can manage your accessory services via MRSK as well. Accessories are long-lived services that your app depends on. They are not updated when you deploy. diff --git a/lib/mrsk/commands/builder/base.rb b/lib/mrsk/commands/builder/base.rb index 15c6b1889..ccef6ab9c 100644 --- a/lib/mrsk/commands/builder/base.rb +++ b/lib/mrsk/commands/builder/base.rb @@ -10,7 +10,7 @@ def pull end def build_options - [ *build_tags, *build_labels, *build_args, *build_secrets, *build_dockerfile ] + [ *build_tags, *build_labels, *build_args, *build_secrets, *build_ssh, *build_dockerfile ] end def build_context @@ -34,6 +34,10 @@ def build_secrets argumentize "--secret", secrets.collect { |secret| [ "id", secret ] } end + def build_ssh + argumentize "--ssh", ssh_args + end + def build_dockerfile argumentize "--file", dockerfile end @@ -42,6 +46,14 @@ def args (config.builder && config.builder["args"]) || {} end + def ssh_args + if config.builder && config.builder["ssh"] + "default=#{config.builder["ssh"]}" + else + "default" + end + end + def secrets (config.builder && config.builder["secrets"]) || [] end diff --git a/test/cli/build_test.rb b/test/cli/build_test.rb index a610d8496..0d5f224d1 100644 --- a/test/cli/build_test.rb +++ b/test/cli/build_test.rb @@ -10,7 +10,7 @@ class CliBuildTest < CliTestCase test "push" do run_command("push").tap do |output| - assert_match /docker buildx build --push --platform linux\/amd64,linux\/arm64 --builder mrsk-app-multiarch -t dhh\/app:999 -t dhh\/app:latest --label service="app" --file Dockerfile \. as .*@localhost/, output + assert_match /docker buildx build --push --platform linux\/amd64,linux\/arm64 --builder mrsk-app-multiarch -t dhh\/app:999 -t dhh\/app:latest --label service="app" --ssh default --file Dockerfile \. as .*@localhost/, output end end diff --git a/test/commands/builder_test.rb b/test/commands/builder_test.rb index 1ecea021a..9d518e1e6 100644 --- a/test/commands/builder_test.rb +++ b/test/commands/builder_test.rb @@ -9,7 +9,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder = new_builder_command assert_equal "multiarch", builder.name assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --ssh default --file Dockerfile .", builder.push.join(" ") end @@ -17,7 +17,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder = new_builder_command(builder: { "multiarch" => false }) assert_equal "native", builder.name assert_equal \ - "docker build -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile . && docker push dhh/app:123 && docker push dhh/app:latest", + "docker build -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --ssh default --file Dockerfile . && docker push dhh/app:123 && docker push dhh/app:latest", builder.push.join(" ") end @@ -25,7 +25,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder = new_builder_command(builder: { "local" => { }, "remote" => { } }) assert_equal "multiarch/remote", builder.name assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch-remote -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch-remote -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --ssh default --file Dockerfile .", builder.push.join(" ") end @@ -33,56 +33,56 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder = new_builder_command(builder: { "remote" => { "arch" => "amd64" } }) assert_equal "native/remote", builder.name assert_equal \ - "docker buildx build --push --platform linux/amd64 --builder mrsk-app-native-remote -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64 --builder mrsk-app-native-remote -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --ssh default --file Dockerfile .", builder.push.join(" ") end test "build args" do builder = new_builder_command(builder: { "args" => { "a" => 1, "b" => 2 } }) assert_equal \ - "-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --file Dockerfile", + "-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --ssh default --file Dockerfile", builder.target.build_options.join(" ") end test "build secrets" do builder = new_builder_command(builder: { "secrets" => ["token_a", "token_b"] }) assert_equal \ - "-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --secret id=\"token_a\" --secret id=\"token_b\" --file Dockerfile", + "-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --secret id=\"token_a\" --secret id=\"token_b\" --ssh default --file Dockerfile", builder.target.build_options.join(" ") end test "build dockerfile" do builder = new_builder_command(builder: { "dockerfile" => "Dockerfile.xyz" }) assert_equal \ - "-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile.xyz", + "-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --ssh default --file Dockerfile.xyz", builder.target.build_options.join(" ") end test "build context" do builder = new_builder_command(builder: { "context" => ".." }) assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile ..", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --ssh default --file Dockerfile ..", builder.push.join(" ") end test "native push with build args" do builder = new_builder_command(builder: { "multiarch" => false, "args" => { "a" => 1, "b" => 2 } }) assert_equal \ - "docker build -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --file Dockerfile . && docker push dhh/app:123 && docker push dhh/app:latest", + "docker build -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --ssh default --file Dockerfile . && docker push dhh/app:123 && docker push dhh/app:latest", builder.push.join(" ") end test "multiarch push with build args" do builder = new_builder_command(builder: { "args" => { "a" => 1, "b" => 2 } }) assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --ssh default --file Dockerfile .", builder.push.join(" ") end test "native push with with build secrets" do builder = new_builder_command(builder: { "multiarch" => false, "secrets" => [ "a", "b" ] }) assert_equal \ - "docker build -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --secret id=\"a\" --secret id=\"b\" --file Dockerfile . && docker push dhh/app:123 && docker push dhh/app:latest", + "docker build -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --secret id=\"a\" --secret id=\"b\" --ssh default --file Dockerfile . && docker push dhh/app:123 && docker push dhh/app:latest", builder.push.join(" ") end diff --git a/test/integration/docker/vm/Dockerfile b/test/integration/docker/vm/Dockerfile index 1fcb92784..e965445ae 100644 --- a/test/integration/docker/vm/Dockerfile +++ b/test/integration/docker/vm/Dockerfile @@ -3,8 +3,7 @@ FROM ubuntu:22.10 WORKDIR /work RUN apt-get update && apt-get -y install openssh-client openssh-server docker.io - -RUN mkdir /root/.ssh && ln -s /shared/ssh/id_rsa.pub /root/.ssh/authorized_keys +RUN mkdir /root/.ssh && ln -s /shared/ssh/id_rsa.pub /root/.ssh/authorized_keys && ssh-keyscan github.com >> ~/.ssh/known_hosts RUN mkdir -p /etc/docker/certs.d/registry:4443 && ln -s /shared/certs/domain.crt /etc/docker/certs.d/registry:4443/ca.crt COPY boot.sh .