So a common problem that I’ve seen is to have to move files from one environment to another that is largely disconnected. This came up in the space industry heavily as we saw that your average spacecraft is in an air-gapped lab while it’s being worked on, and then after launch has very limited bandwidth. I’ve seen this in other regulated industries as well. There continues to be a common problem of how do I move files and container images between these environments.
The challenge isn’t always that I don’t know how to do the move, but rather caused by the fact that I have numerous types of artifacts to move between environments.
Additionally moving these types of artifacts comes with other challenges because when you are keeping multiple copies of files, how can I do that and still maintain a single source of truth, or even version the files to identify differences.
The best solution I’ve found so far is to leverage OCI artifacts to perform this kind of migration. OCI stands for Open Container Initiative, and what this standard has sought to do is create a standard for all containers and registries to make this easier to accomplish. Along with standardizing the way that we store containers and artifacts, this has given way to new technologies like regclient, and oras.
So what’s the problem?
So if we take a step back, the problem is the following:
sequenceDiagram
participant Source
participant Registry
participant Destination
Source->>Registry: Use Oras to Push file.
Registry->>Destination: Use Oras to pull file.
The biggest benefits of this approach is that it turns the container registry into the “Meet Me” point by which we interface between either sides of the deployment.
Now shortly I’m going to take this a step further to show moving across an airgap, but first lets get some artifacts on the registry.
How do I do this?
So below are the steps for perform these operations, let’s start with installing oras, for full documentation see here.
Install Oras:
Step 1 – I installed this on WSL using Ubuntu 22.04 LTS using the following:
# NOTE: Update to the current version number.
VERSION="1.2.2"
curl -LO "https://github.com/oras-project/oras/releases/download/v${VERSION}/oras_${VERSION}_linux_amd64.tar.gz"
mkdir -p oras-install/
tar -zxf oras_${VERSION}_*.tar.gz -C oras-install/
sudo mv oras-install/oras /usr/local/bin/
rm -rf oras_${VERSION}_*.tar.gz oras-install/
I then confirmed it installed by doing the following:
oras version
And got the following:
Version: 1.2.2
Go version: go1.23.4
Git commit: 677529b4e7c38e3295e0883a2ee8a536e3a860f4
Git tree state: clean
Now if you need to install oras as part of a github actions workflow, you can use the following composite action:
name: 'install-oras'
description: 'Installs oras'
inputs:
oras-version:
description: 'The version of oras to install'
default: '0.16.0'
runs:
using: 'composite'
steps:
- name: Install oras
shell: bash
run: |
arch="$(uname -m)"
case "$arch" in
x86_64)
architecture=amd64
;;
aarch64)
architecture=arm64
;;
*)
echo "Unsupported architecture: $arch"
exit 1
;;
esac
echo "Installing oras version ${{ inputs.oras-version }} for $architecture"
curl -LO https://github.com/oras-project/oras/releases/download/v${{ inputs.oras-version }}/oras_${{ inputs.oras-version }}_linux_${architecture}.tar.gz
mkdir -p oras-install/
tar -zxf oras_${{ inputs.oras-version }}_*.tar.gz -C oras-install/
sudo mv oras-install/oras /usr/local/bin/
rm -rf oras_${{ inputs.oras-version }}_*.tar.gz oras-install/
Push File to Registry:
For the following I’m going to create a simple text file to show how to move the files between the registry:
echo "Moving file test" | cat > ./test-file.txt
Then I need to log into my container registry using the following:
az cloud set --name AzureUSGovernment
az login --use-device-code
Then you will need to log into the container registry:
acr_registry_name="orasregistry" # Replace with the name of your registry
az acr login --name $acr_registry_name
When the login process is done, you should see a “Login Succeeded.”
Then run this command to perform the push to the registry:
oras push orasregistry.azurecr.us/test/file:0.0.1,latest ./test-file.txt
Once that is complete, if you go to the registry itself, you will see the repository:
Notice that in my command, I gave this version of the file the “0.0.1” tag, and the latest tag. Then to show versioning of the file, I’m going to update that file with this command.
echo "Moving file test v2" | cat > ./test-file.txt
And then I’m going to run the following command:
oras push orasregistry.azurecr.us/test/file:0.0.2,latest ./test-file.txt
Now if you check your registry, you will see that the tags show “0.0.1”, “0.0.2”, and “latest”
Ideally these pushes would all be from a CI/CD system into the registry through automation, and the idea is other developers or production applications could pull down the files from the registry.
Pulling a file from a registry:
Now that we’ve pushed the files up there, we need to pull them down. Step 1 would be to log in on the other side of the registry and install oras same as above. You can then accomplish this by doing the following:
From the other side, perform the same login steps:
az cloud set --name AzureUSGovernment
az login --use-device-code
Then you will need to log into the container registry:
acr_registry_name="orasregistry" # Replace with the name of your registry
az acr login --name $acr_registry_name
Then run the following command:
oras pull orasregistry.azurecr.us/test/file:latest
Now if I perform a tree command (tree .) on the directory I just perform the pull from, I will see the file:
.
└── test-file.txt
And the contents of the file will be:
Moving file test v2
Notice this matches the second file we pushed. If I wanted to pull the original file, I could run the following:
oras pull orasregistry.azurecr.us/test/file:0.0.1
And you will see that it has overwritten the file with the contents of the original push:
Moving file test