Docker with Private SPM Dependencies

Posted Tuesday, January 12, 2021.

SSH vs HTTPS

I've only been able to get this to work when private package dependencies were declared using ssh urls. Take the following package for example:

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Test",
dependencies: [
.package(url: "git@github.com:hiimtmac/component-kit.git", from: "1.0.0")
// .package(url: "https://github.com/hiimtmac/component-kit.git", from: "1.0.0") // does not work
],
targets: [
.target(
name: "App",
dependencies: [
.product(name: "ComponentKit", package: "component-kit")
],
])
]
)

Assuming your ssh key has been setup on GitHub properly, this will pull with no problems. But as soon as it is being built within a docker container, it doesn't have access to your SSH key.

For my organization, I have setup a dummy build user that only has read access to all our private repos. I generated a new ssh key on my computer (storing it in ~/.ssh/github_rsa). Then I uploaded the public key to github under that build user's account. I didn't want my private key to be in the dockerfile at any point so this is why I chose that route.

Adjust the Dockerfile

Our current dockerfile might look something like this:

FROM swift:5.3-focal

# Copy entire repo into container
COPY . .

# Compile with optimizations
RUN swift build \
--enable-test-discovery \
-c release

We will make a couple changes so that the package manager wont hit any snags when pulling our private package:

FROM swift:5.3-focal

ARG GITHUB_SSH

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
chmod 0700 /root/.ssh && \
ssh-keyscan github.com > /root/.ssh/known_hosts

# Add the keys and set permissions
RUN echo "$GITHUB_SSH" > /root/.ssh/id_rsa && \
chmod 600 /root/.ssh/id_rsa

# Copy entire repo into container
COPY . .

# Compile with optimizations
RUN swift build \
--enable-test-discovery \
-c release

# Remove SSH keys
RUN rm -rf /root/.ssh/

The GITHUB_SSH arg can then be injected at build time so that there is a ssh key with permission to clone the repo. This build command will look like this:

docker build --build-arg GITHUB_SSH="$(cat ~/.ssh/github_rsa)" -t hiimtmac/cool-app .

In Closing

Make sure your GitHub account has at least read access to the repo of the private dependency. This mechanism for building SPM applications with private dependencies has worked well for me. If there is a better/more secure way to go about this, please let me know!


Tagged With: