├── talk-at-kcd-munich-2023.md
├── .gitignore
├── assets
├── quay-4eab20bcf7da.png
├── quay-76535c50cab1.png
├── quay-d3b7a48ede60.png
├── quay-4eab20bcf7da-hl.png
├── quay-76535c50cab1-hl.png
└── quay-multi-arch-overview.png
├── setup-demo-env
├── hcloud.yaml
├── hosts.yaml
├── destroy-hcloud-instances.yaml
├── ansible-navigator.yaml
├── ansible.cfg
└── create-hcloud-instances.yaml
├── Containerfile.windows
├── Containerfile
├── .tekton
└── multi-arch.yaml
├── LICENSE
└── README.md
/talk-at-kcd-munich-2023.md:
--------------------------------------------------------------------------------
1 | README.md
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | print-runtime-*
2 | ansible-navigator.log
3 |
--------------------------------------------------------------------------------
/assets/quay-4eab20bcf7da.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshift-examples/multi-arch/HEAD/assets/quay-4eab20bcf7da.png
--------------------------------------------------------------------------------
/assets/quay-76535c50cab1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshift-examples/multi-arch/HEAD/assets/quay-76535c50cab1.png
--------------------------------------------------------------------------------
/assets/quay-d3b7a48ede60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshift-examples/multi-arch/HEAD/assets/quay-d3b7a48ede60.png
--------------------------------------------------------------------------------
/assets/quay-4eab20bcf7da-hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshift-examples/multi-arch/HEAD/assets/quay-4eab20bcf7da-hl.png
--------------------------------------------------------------------------------
/assets/quay-76535c50cab1-hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshift-examples/multi-arch/HEAD/assets/quay-76535c50cab1-hl.png
--------------------------------------------------------------------------------
/setup-demo-env/hcloud.yaml:
--------------------------------------------------------------------------------
1 | plugin: hcloud
2 | token: "{{ lookup('ansible.builtin.env', 'HCLOUD_MULTI_ARCH_TOKEN') }}"
3 |
4 |
--------------------------------------------------------------------------------
/Containerfile.windows:
--------------------------------------------------------------------------------
1 | ARG WINVER=ltsc2022
2 | FROM mcr.microsoft.com/windows/servercore:${WINVER}
3 |
4 | CMD echo Hello from Windows
--------------------------------------------------------------------------------
/assets/quay-multi-arch-overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshift-examples/multi-arch/HEAD/assets/quay-multi-arch-overview.png
--------------------------------------------------------------------------------
/setup-demo-env/hosts.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | laptop:
3 | hosts:
4 | laptop:
5 | ansible_host: 127.0.0.1
6 | ansible_user: rbohne
7 |
--------------------------------------------------------------------------------
/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/ubi-micro AS runner
2 |
3 | # Run a command, to have an architecture-specific action during the build
4 | RUN uname -om
5 |
6 | CMD ["uname","-om" ]
7 |
--------------------------------------------------------------------------------
/setup-demo-env/destroy-hcloud-instances.yaml:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ansible-playbook
2 | ---
3 | - name: Destroy all hcloud_instance
4 | hosts: hcloud
5 | gather_facts: no
6 | tasks:
7 | - name: "Destroy {{ name }}"
8 | hcloud_server:
9 | api_token: "{{ lookup('ansible.builtin.env', 'HCLOUD_MULTI_ARCH_TOKEN') }}"
10 | name: "{{ name }}"
11 | state: absent
12 |
--------------------------------------------------------------------------------
/setup-demo-env/ansible-navigator.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | ansible-navigator:
3 | ansible:
4 | inventory:
5 | entries:
6 | - hcloud.yaml
7 | - hosts.yaml
8 | execution-environment:
9 | container-options:
10 | - --net=host
11 | environment-variables:
12 | pass:
13 | - HCLOUD_MULTI_ARCH_TOKEN
14 | image: quay.io/rbohne/lab-ee:latest
15 | logging:
16 | level: info
17 | mode: stdout
18 | playbook-artifact:
19 | enable: false
20 |
--------------------------------------------------------------------------------
/setup-demo-env/ansible.cfg:
--------------------------------------------------------------------------------
1 | # config file for ansible -- http://ansible.com/
2 | # ==============================================
3 |
4 | # This config file provides examples for running
5 | # the OpenShift playbooks with the provided
6 | # inventory scripts.
7 |
8 | [defaults]
9 | # Set the log_path
10 | log_path = ~/ansible.log
11 |
12 | # Additional default options for OpenShift Ansible
13 | forks = 20
14 | host_key_checking = False
15 | retry_files_enabled = False
16 | retry_files_save_path = ~/ansible-installer-retries
17 | nocows = True
18 | remote_user = root
19 | # roles_path = roles/
20 | gathering = smart
21 | # fact_caching = jsonfile
22 | # fact_caching_connection = $HOME/ansible/facts
23 | # fact_caching_timeout = 600
24 | callbacks_enabled = profile_tasks
25 | # callbacks_enabled
26 | inventory_ignore_extensions = secrets.py, .pyc, .cfg, .crt, .ini
27 | # work around privilege escalation timeouts in ansible:
28 | timeout = 30
29 |
30 | # Uncomment to use the provided example inventory
31 | inventory = hosts.yaml
32 |
33 | ansible_python_interpreter = auto
34 |
35 | # Additional ssh options for OpenShift Ansible
36 | [ssh_connection]
37 | pipelining = True
38 | ssh_args = -o ControlMaster=auto -o ControlPersist=600s
39 | timeout = 10
40 | # shorten the ControlPath which is often too long; when it is,
41 | # ssh connection reuse silently fails, making everything slower.
42 | control_path = %(directory)s/%%h-%%r
--------------------------------------------------------------------------------
/setup-demo-env/create-hcloud-instances.yaml:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ansible-playbook
2 | ---
3 | - name: Start hcloud_instance
4 | hosts: laptop
5 | gather_facts: no
6 | tasks:
7 | - name: Create arm-instance
8 | delegate_to: localhost
9 | hetzner.hcloud.hcloud_server:
10 | api_token: "{{ lookup('ansible.builtin.env', 'HCLOUD_MULTI_ARCH_TOKEN') }}"
11 | name: arm-instance
12 | server_type: cax11
13 | image: fedora-38
14 | location: fsn1
15 | state: present
16 | enable_ipv6: false
17 | ssh_keys:
18 | - rbohne@redhat.com
19 | register: output
20 |
21 | - name: Update ~/.ssh/config
22 | blockinfile:
23 | path: ~/.ssh/config
24 | marker: "# {mark} - multi-arch arm-instance "
25 | block: |
26 | Host arm-instance
27 | HostName {{ output.hcloud_server.ipv4_address }}
28 | User root
29 |
30 | - name: Wait 300 seconds for port 22 to become open
31 | delegate_to: localhost
32 | ansible.builtin.wait_for:
33 | port: 22
34 | host: '{{ output.hcloud_server.ipv4_address }}'
35 | delay: 1
36 | timeout: 300
37 | connection: local
38 |
39 | - name: Create x86-instance
40 | delegate_to: localhost
41 | hetzner.hcloud.hcloud_server:
42 | api_token: "{{ lookup('ansible.builtin.env', 'HCLOUD_MULTI_ARCH_TOKEN') }}"
43 | name: x86-instance
44 | server_type: cx11
45 | image: fedora-38
46 | location: fsn1
47 | state: present
48 | enable_ipv6: false
49 | ssh_keys:
50 | - rbohne@redhat.com
51 | register: output
52 |
53 | - name: Update ~/.ssh/config
54 | blockinfile:
55 | path: ~/.ssh/config
56 | marker: "# {mark} - multi-arch x86-instance "
57 | block: |
58 | Host x86-instance
59 | HostName {{ output.hcloud_server.ipv4_address }}
60 | User root
61 |
62 | - name: Wait 300 seconds for port 22 to become open
63 | delegate_to: localhost
64 | ansible.builtin.wait_for:
65 | port: 22
66 | host: '{{ output.hcloud_server.ipv4_address }}'
67 | delay: 1
68 | timeout: 300
69 | connection: local
70 |
71 | - name: refresh_inventory
72 | ansible.builtin.meta: refresh_inventory
73 |
74 | - name: Install packages
75 | hosts: hcloud
76 | gather_facts: no
77 | tasks:
78 | # sudo dnf install podman skopeo buildah jq git tmux
79 | - name: Install packages
80 | ansible.builtin.dnf:
81 | name:
82 | - podman
83 | - skopeo
84 | - buildah
85 | - jq
86 | - git
87 | - tmux
88 | state: latest
89 | # git clone https://github.com/openshift-examples/multi-arch.git
90 | - name: Clone demo repo
91 | ansible.builtin.git:
92 | repo: https://github.com/openshift-examples/multi-arch.git
93 | dest: /root/multi-arch
94 |
--------------------------------------------------------------------------------
/.tekton/multi-arch.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: PipelineRun
3 | metadata:
4 | name: multi-arch
5 |
6 | labels:
7 | tekton.dev/pipeline: multi-arch
8 | annotations:
9 | pipelinesascode.tekton.dev/on-event: "[push]"
10 | # The branch or tag we are targeting (ie: main, refs/tags/*)
11 | pipelinesascode.tekton.dev/on-target-branch: "[main,devel]"
12 |
13 | pipelinesascode.tekton.dev/task: "git-clone"
14 | pipelinesascode.tekton.dev/task-1: "buildah"
15 |
16 | # Use maven task from hub
17 | # pipelinesascode.tekton.dev/task-1: "[pre-commit]"
18 |
19 | # You can add more tasks in here to reuse, browse the one you like from here
20 | # https://hub.tekton.dev/
21 | # example:
22 | # pipelinesascode.tekton.dev/task-2: "[.tekton/task/github-add-labels.yaml]"
23 | # pipelinesascode.tekton.dev/task-3: "[.tekton/task/github-add-comment.yaml]"
24 |
25 | # How many runs we want to keep attached to this event
26 | pipelinesascode.tekton.dev/max-keep-runs: "1"
27 |
28 | spec:
29 | params:
30 |
31 | taskRunSpecs:
32 | # Build the amd64 image on dedicated amd64 hardware
33 | - pipelineTaskName: build-on-amd64
34 | taskPodTemplate:
35 | nodeSelector:
36 | kubernetes.io/arch: amd64
37 | # Build the arm64 image on dedicated arm64 hardware
38 | - pipelineTaskName: build-on-arm64
39 | taskPodTemplate:
40 | nodeSelector:
41 | kubernetes.io/arch: arm64
42 |
43 | pipelineSpec:
44 | params:
45 | #- name: repo_url
46 | #- name: revision
47 | workspaces:
48 | - name: source
49 | - name: push-secret
50 | tasks:
51 | - name: git-clone
52 | params:
53 | - name: url
54 | value: 'https://github.com/openshift-examples/multi-arch.git'
55 | - name: revision
56 | value: main
57 | taskRef:
58 | kind: ClusterTask
59 | name: git-clone
60 | workspaces:
61 | - name: output
62 | workspace: source
63 |
64 | - name: build-on-arm64
65 | params:
66 | - name: IMAGE
67 | value: 'quay.io/openshift-examples/multi-arch:pac-arm64'
68 | - name: DOCKERFILE
69 | value: ./Containerfile
70 | runAfter:
71 | - git-clone
72 | taskRef:
73 | kind: ClusterTask
74 | name: buildah
75 | workspaces:
76 | - name: source
77 | workspace: source
78 | - name: dockerconfig
79 | workspace: push-secret
80 |
81 | - name: build-on-amd64
82 | params:
83 | - name: IMAGE
84 | value: 'quay.io/openshift-examples/multi-arch:pac-amd64'
85 | - name: DOCKERFILE
86 | value: ./Containerfile
87 | runAfter:
88 | - build-on-arm64
89 | taskRef:
90 | kind: ClusterTask
91 | name: buildah
92 | workspaces:
93 | - name: source
94 | workspace: source
95 | - name: dockerconfig
96 | workspace: push-secret
97 |
98 | - name: create-and-push-manifest
99 | runAfter:
100 | - build-on-amd64
101 | params:
102 | - name: IMAGE
103 | value: 'quay.io/openshift-examples/multi-arch:pac'
104 | - name: IMAGE_URL_AMD64
105 | value: $(tasks.build-on-amd64.results.IMAGE_URL)
106 | - name: IMAGE_URL_ARM64
107 | value: $(tasks.build-on-arm64.results.IMAGE_URL)
108 | workspaces:
109 | - name: source
110 | workspace: source
111 | - name: dockerconfig
112 | workspace: push-secret
113 | taskSpec:
114 | volumes:
115 | - emptyDir: {}
116 | name: varlibcontainers
117 | workspaces:
118 | - name: source
119 | - description: >-
120 | An optional workspace that allows providing a .docker/config.json file
121 | for Buildah to access the container registry. The file should be placed
122 | at the root of the Workspace with name config.json or .dockerconfigjson.
123 | name: dockerconfig
124 | optional: true
125 | params:
126 | - description: Reference of the image buildah will produce.
127 | name: IMAGE
128 | type: string
129 | - default: >-
130 | registry.redhat.io/rhel8/buildah@sha256:00795fafdab9bbaa22cd29d1faa1a01e604e4884a2c935c1bf8e3d1f0ad1c084
131 | description: The location of the buildah builder image.
132 | name: BUILDER_IMAGE
133 | type: string
134 | - name: IMAGE_URL_AMD64
135 | type: string
136 | - name: IMAGE_URL_ARM64
137 | type: string
138 | steps:
139 | - name: create-and-push
140 | image: $(params.BUILDER_IMAGE)
141 | env:
142 | - name: IMAGE_URL_AMD64
143 | value: $(params.IMAGE_URL_AMD64)
144 | - name: IMAGE_URL_ARM64
145 | value: $(params.IMAGE_URL_ARM64)
146 | securityContext:
147 | capabilities:
148 | add:
149 | - SETFCAP
150 | volumeMounts:
151 | - mountPath: /var/lib/containers
152 | name: varlibcontainers
153 | workingDir: $(workspaces.source.path)
154 | script: |
155 | if [[ "$(workspaces.dockerconfig.bound)" == "true" ]]; then
156 |
157 | # if config.json exists at workspace root, we use that
158 | if test -f "$(workspaces.dockerconfig.path)/config.json"; then
159 | export DOCKER_CONFIG="$(workspaces.dockerconfig.path)"
160 |
161 | # else we look for .dockerconfigjson at the root
162 | elif test -f "$(workspaces.dockerconfig.path)/.dockerconfigjson"; then
163 | cp "$(workspaces.dockerconfig.path)/.dockerconfigjson" "$HOME/.docker/config.json"
164 | export DOCKER_CONFIG="$HOME/.docker"
165 |
166 | # need to error out if neither files are present
167 | else
168 | echo "neither 'config.json' nor '.dockerconfigjson' found at workspace root"
169 | exit 1
170 | fi
171 | fi
172 | set -x
173 | buildah manifest create localhost/list
174 | buildah manifest add localhost/list $IMAGE_URL_AMD64
175 | buildah manifest add localhost/list $IMAGE_URL_ARM64
176 | buildah manifest push localhost/list docker://$(params.IMAGE)
177 |
178 | workspaces:
179 | - name: source
180 | volumeClaimTemplate:
181 | metadata:
182 | creationTimestamp: null
183 | spec:
184 | accessModes:
185 | - ReadWriteOnce
186 | resources:
187 | requests:
188 | storage: 1Gi
189 | volumeMode: Filesystem
190 | - name: push-secret
191 | secret:
192 | secretName: quay-push-bot
193 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Demystifying Container Images: Unveiling the Secrets of Multi-Architecture, Manifests, IDs, and Digests
2 |
3 | ## Build container image (amd64/x86_64)
4 |
5 | ```bash
6 | [root@x86-instance multi-arch]# buildah bud -f Containerfile \
7 | -t quay.io/openshift-examples/multi-arch:demo-$(uname -m) .
8 | STEP 1/2: FROM registry.access.redhat.com/ubi9/ubi-micro AS runner
9 | Trying to pull registry.access.redhat.com/ubi9/ubi-micro:latest...
10 | Getting image source signatures
11 | Checking if image destination supports signatures
12 | Copying blob 9e167103aefa done
13 | Copying config 1b9d4f56fb done
14 | Writing manifest to image destination
15 | Storing signatures
16 | STEP 2/2: CMD ["uname","-om" ]
17 | COMMIT quay.io/openshift-examples/multi-arch:demo-x86_64
18 | Getting image source signatures
19 | Copying blob a3ede86005c1 skipped: already exists
20 | Copying blob 5f70bf18a086 done
21 | Copying config 81b91103bc done
22 | Writing manifest to image destination
23 | --> 81b91103bcad
24 | Successfully tagged quay.io/openshift-examples/multi-arch:demo-x86_64
25 | 81b91103bcad946edabad074db3e3eefcbfccd307587b6b40257bb0932a31705
26 | ```
27 |
28 | List images (not pushed, yet)
29 | ```
30 | [root@x86-instance multi-arch]# podman images --digests --no-trunc
31 | REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
32 | quay.io/openshift-examples/multi-arch demo-x86_64 sha256:66ade3f15bca773a0227d4ff479bb1191b5e5bb94da88bab7307284129bb1733 sha256:81b91103bcad946edabad074db3e3eefcbfccd307587b6b40257bb0932a31705 28 seconds ago 26.1 MB
33 | registry.access.redhat.com/ubi9/ubi-micro latest sha256:bd93cff066cc579e49d53f50782f7edad319031e9d511b1e8709cf16be8d78a0 sha256:1b9d4f56fb2cd4401fa14437e3f245e6872388ed3e50f72926234315cbf4f817 3 weeks ago 26.1 MB
34 | ```
35 |
36 |
37 | Discover image details - Manifest (`sha256:66ade3f15bca`)
38 |
39 | ### Discover image details - Manifest (`sha256:66ade3f15bca`)
40 |
41 | ```bash
42 | # Get Digest
43 | [root@x86-instance multi-arch]# skopeo inspect --raw containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m) | sha256sum
44 | INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
45 | 66ade3f15bca773a0227d4ff479bb1191b5e5bb94da88bab7307284129bb1733 -
46 | ```
47 |
48 | ```json
49 | {
50 | "schemaVersion": 2,
51 | "mediaType": "application/vnd.oci.image.manifest.v1+json",
52 | "config": {
53 | "mediaType": "application/vnd.oci.image.config.v1+json",
54 | "digest": "sha256:81b91103bcad946edabad074db3e3eefcbfccd307587b6b40257bb0932a31705",
55 | "size": 4245
56 | },
57 | "layers": [
58 | {
59 | "mediaType": "application/vnd.oci.image.layer.v1.tar",
60 | "digest": "sha256:a3ede86005c19f841273a0c4b8ee64628a029794025b7274cb8cbd4c9d2c6e11",
61 | "size": 26085888
62 | },
63 | {
64 | "mediaType": "application/vnd.oci.image.layer.v1.tar",
65 | "digest": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
66 | "size": 1024
67 | }
68 | ],
69 | "annotations": {
70 | "org.opencontainers.image.base.digest": "sha256:a54f5a7a9b67f32b6ae402cf0659ba4a3fd8eed4bdcbd00b5514ce4450b31214",
71 | "org.opencontainers.image.base.name": "registry.access.redhat.com/ubi9/ubi-micro:latest"
72 | }
73 | }
74 | ```
75 |
76 |
77 |
78 | Discover image details - Config (`sha256:81b91103bcad`)
79 |
80 | ### Discover image details - Config (`sha256:81b91103bcad`)
81 |
82 | ```bash
83 | # Get ImageID
84 | [root@x86-instance multi-arch]# skopeo inspect --raw containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m) | jq '.config.digest'
85 | INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
86 | "sha256:81b91103bcad946edabad074db3e3eefcbfccd307587b6b40257bb0932a31705"
87 | [root@x86-instance multi-arch]#
88 | ```
89 |
90 | `skopeo inspect --config containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m)`:
91 | ```json
92 | {
93 | "created": "2023-10-01T19:27:45.860244628Z",
94 | "architecture": "amd64",
95 | "os": "linux",
96 | "config": {
97 | "Env": [
98 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
99 | ],
100 | "Cmd": [
101 | "uname",
102 | "-om"
103 | ],
104 | "Labels": {
105 | [...snipped...]
106 | }
107 | },
108 | "rootfs": {
109 | "type": "layers",
110 | "diff_ids": [
111 | "sha256:a3ede86005c19f841273a0c4b8ee64628a029794025b7274cb8cbd4c9d2c6e11",
112 | "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
113 | ]
114 | }
115 | "history": [
116 | [...snipped...]
117 | ]
118 | }
119 | ```
120 |
121 |
122 | ## Push container image (amd64/x86_64)
123 |
124 | ```
125 | [root@x86-instance multi-arch]# podman push quay.io/openshift-examples/multi-arch:demo-$(uname -m)
126 | Getting image source signatures
127 | Copying blob 5f70bf18a086 done |
128 | Copying blob a3ede86005c1 done |
129 | Copying config 81b91103bc done |
130 | Writing manifest to image destination
131 | ```
132 |
133 | 
134 |
135 |
136 | ## 😱 Different digest
137 |
138 |
139 | ```bash
140 | # Get Manifest from local image
141 | [root@x86-instance multi-arch]# skopeo inspect --raw containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m) > 66ade3f15bca.json
142 | INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
143 |
144 | # Get Manifest from image in container registry
145 | [root@x86-instance multi-arch]# skopeo inspect --raw docker://quay.io/openshift-examples/multi-arch:demo-$(uname -m) > 76535c50cab1.json
146 |
147 | # Double check sha256sum
148 | [root@x86-instance multi-arch]# sha256sum *json
149 | 66ade3f15bca773a0227d4ff479bb1191b5e5bb94da88bab7307284129bb1733 66ade3f15bca.json
150 | 76535c50cab1708ff17dc67e93d2a06dea01978f7201d17fd6b28b32f8ce9555 76535c50cab1.json
151 |
152 | # "Cleanup" json
153 | [root@x86-instance multi-arch]# jq . 66ade3f15bca.json > 66ade3f15bca.pretty.json
154 | [root@x86-instance multi-arch]# jq . 76535c50cab1.json > 76535c50cab1.pretty.json
155 |
156 | # Diff
157 | [root@x86-instance multi-arch]# diff -Nuar 66ade3f15bca.pretty.json 76535c50cab1.pretty.json
158 | ```
159 | ```diff
160 | --- 66ade3f15bca.pretty.json 2023-10-01 19:41:38.331150221 +0000
161 | +++ 76535c50cab1.pretty.json 2023-10-01 19:41:46.923176546 +0000
162 | @@ -8,14 +8,14 @@
163 | },
164 | "layers": [
165 | {
166 | - "mediaType": "application/vnd.oci.image.layer.v1.tar",
167 | - "digest": "sha256:a3ede86005c19f841273a0c4b8ee64628a029794025b7274cb8cbd4c9d2c6e11",
168 | - "size": 26085888
169 | + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
170 | + "digest": "sha256:9e167103aefa56af4c39359687f54fdd263ca85bc946e770d92c054df7ada57c",
171 | + "size": 7686605
172 | },
173 | {
174 | - "mediaType": "application/vnd.oci.image.layer.v1.tar",
175 | - "digest": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
176 | - "size": 1024
177 | + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
178 | + "digest": "sha256:bd9ddc54bea929a22b334e73e026d4136e5b73f5cc29942896c72e4ece69b13d",
179 | + "size": 34
180 | }
181 | ],
182 | "annotations": {
183 | ```
184 |
185 | ## Build and Push container image (arm64/aarch64)
186 |
187 |
188 | ```bash
189 | [root@arm-instance multi-arch]# buildah bud -f Containerfile \
190 | -t quay.io/openshift-examples/multi-arch:demo-$(uname -m) .
191 | STEP 1/2: FROM registry.access.redhat.com/ubi9/ubi-micro AS runner
192 | Trying to pull registry.access.redhat.com/ubi9/ubi-micro:latest...
193 | Getting image source signatures
194 | Checking if image destination supports signatures
195 | Copying blob 76f837f08b76 done
196 | Copying config 97f43b6789 done
197 | Writing manifest to image destination
198 | Storing signatures
199 | STEP 2/2: CMD ["uname","-om" ]
200 | COMMIT quay.io/openshift-examples/multi-arch:demo-aarch64
201 | Getting image source signatures
202 | Copying blob 791a6a33d694 skipped: already exists
203 | Copying blob 5f70bf18a086 done
204 | Copying config 01d89888b7 done
205 | Writing manifest to image destination
206 | --> 01d89888b7ef
207 | Successfully tagged quay.io/openshift-examples/multi-arch:demo-aarch64
208 | 01d89888b7ef4cb7709345dd8f5f9a9ee352007a613f2b41fed11571f6f53a95
209 | ```
210 |
211 | List images (not pushed, yet)
212 | ```
213 | [root@arm-instance multi-arch]# podman images --digests --no-trunc
214 | REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
215 | quay.io/openshift-examples/multi-arch demo-aarch64 sha256:c3bb20ed9d0466c9234763764baab5b5ffd7bd87e5ca2459c889c5ddbe411fbe sha256:01d89888b7ef4cb7709345dd8f5f9a9ee352007a613f2b41fed11571f6f53a95 31 seconds ago 27.3 MB
216 | registry.access.redhat.com/ubi9/ubi-micro latest sha256:bd93cff066cc579e49d53f50782f7edad319031e9d511b1e8709cf16be8d78a0 sha256:97f43b6789e0162674e5fe274a3b39d4894062b4ec8e5b0c4f9305f43223c797 2 weeks ago 27.3 MB
217 | ```
218 |
219 |
220 | Discover image details - Manifest (`sha256:c3bb20ed9d04`)
221 |
222 | ### Discover image details - Manifest (`sha256:c3bb20ed9d04`)
223 |
224 | ```bash
225 | # Get Digest
226 | [root@arm-instance multi-arch]# skopeo inspect --raw containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m) | sha256sum
227 | INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
228 | c3bb20ed9d0466c9234763764baab5b5ffd7bd87e5ca2459c889c5ddbe411fbe -
229 | ```
230 |
231 | ```json
232 | {
233 | "schemaVersion": 2,
234 | "mediaType": "application/vnd.oci.image.manifest.v1+json",
235 | "config": {
236 | "mediaType": "application/vnd.oci.image.config.v1+json",
237 | "digest": "sha256:01d89888b7ef4cb7709345dd8f5f9a9ee352007a613f2b41fed11571f6f53a95",
238 | "size": 4247
239 | },
240 | "layers": [
241 | {
242 | "mediaType": "application/vnd.oci.image.layer.v1.tar",
243 | "digest": "sha256:791a6a33d694bf7f1a8a1373b17e2cead2c0e2ee17620cd64128acfa88d2a953",
244 | "size": 27290112
245 | },
246 | {
247 | "mediaType": "application/vnd.oci.image.layer.v1.tar",
248 | "digest": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
249 | "size": 1024
250 | }
251 | ],
252 | "annotations": {
253 | "org.opencontainers.image.base.digest": "sha256:937f8e16fda9d9d2dceaa03870bf40d355ef68eea8faa04cd56cd59d6d33866a",
254 | "org.opencontainers.image.base.name": "registry.access.redhat.com/ubi9/ubi-micro:latest"
255 | }
256 | }
257 | ```
258 |
259 |
260 |
261 | Discover image details - Config (`sha256:01d89888b7ef`)
262 |
263 | ### Discover image details - Config (`sha256:01d89888b7ef`)
264 |
265 | ```bash
266 | # Get ImageID
267 | [root@arm-instance multi-arch]# skopeo inspect --raw containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m) | jq '.config.digest'
268 | INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
269 | "sha256:01d89888b7ef4cb7709345dd8f5f9a9ee352007a613f2b41fed11571f6f53a95"
270 | ```
271 |
272 | `skopeo inspect --config containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m)`:
273 | ```json
274 | {
275 | "created": "2023-07-14T11:49:23.062774594Z",
276 | "architecture": "amd64",
277 | "os": "linux",
278 | "config": {
279 | "Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
280 | "Cmd": ["uname","-om"],
281 | "Labels": {
282 | "architecture": "x86_64",
283 | "build-date": "2023-06-15T11:05:34",
284 | [...snipped...]
285 | }
286 | },
287 | "rootfs": {
288 | "type": "layers",
289 | "diff_ids": [
290 | "sha256:e54dc53d0edbbc96d3307fdea7bc1ed433d9083a1aab033dc3b38fd8b4fb165a",
291 | "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
292 | ]
293 | },
294 | "history": [
295 | [...snipped...]
296 | ]
297 | }
298 | ```
299 |
300 |
301 | ## Push container image (amd64/x86_64)
302 |
303 | ```
304 | [root@arm-instance ~]# podman push quay.io/openshift-examples/multi-arch:demo-$(uname -m)
305 | Getting image source signatures
306 | Copying blob 791a6a33d694 done |
307 | Copying blob 5f70bf18a086 done |
308 | Copying config 01d89888b7 done |
309 | Writing manifest to image destination
310 | ```
311 |
312 | 
313 |
314 |
315 | ## 😱 Different digest
316 |
317 |
318 | ```bash
319 | # Get Manifest from local image
320 | [root@arm-instance ~]# skopeo inspect --raw containers-storage:quay.io/openshift-examples/multi-arch:demo-$(uname -m) > c3bb20ed9d04.json
321 | INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
322 |
323 | # Get Manifest from image in container registry
324 | [root@arm-instance overlay]# skopeo inspect --raw docker://quay.io/openshift-examples/multi-arch:demo-$(uname -m) > 4eab20bcf7da.json
325 |
326 | # Double check sha256sum
327 | [root@arm-instance ~]# sha256sum *json
328 | 4eab20bcf7da10905cb95ce80141869e84854d15d99454e1365f10286d519f62 4eab20bcf7da.json
329 | c3bb20ed9d0466c9234763764baab5b5ffd7bd87e5ca2459c889c5ddbe411fbe c3bb20ed9d04.json
330 |
331 | # "Cleanup" json
332 | [root@arm-instance ~]# jq . 4eab20bcf7da.json > 4eab20bcf7da.pretty.json
333 | [root@arm-instance ~]# jq . c3bb20ed9d04.json > c3bb20ed9d04.pretty.json
334 |
335 | # Diff
336 | [root@arm-instance ~]# diff -Nuar 4eab20bcf7da.pretty.json c3bb20ed9d04.pretty.json
337 | ```
338 | ```diff
339 | --- 4eab20bcf7da.pretty.json 2023-10-01 19:22:19.243175721 +0000
340 | +++ c3bb20ed9d04.pretty.json 2023-10-01 19:22:33.857304565 +0000
341 | @@ -8,14 +8,14 @@
342 | },
343 | "layers": [
344 | {
345 | - "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
346 | - "digest": "sha256:76f837f08b7667f5c10d53f91ca4885797a2cfa13f195e9bd024ad9ad934d0d2",
347 | - "size": 7099212
348 | + "mediaType": "application/vnd.oci.image.layer.v1.tar",
349 | + "digest": "sha256:791a6a33d694bf7f1a8a1373b17e2cead2c0e2ee17620cd64128acfa88d2a953",
350 | + "size": 27290112
351 | },
352 | {
353 | - "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
354 | - "digest": "sha256:bd9ddc54bea929a22b334e73e026d4136e5b73f5cc29942896c72e4ece69b13d",
355 | - "size": 34
356 | + "mediaType": "application/vnd.oci.image.layer.v1.tar",
357 | + "digest": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
358 | + "size": 1024
359 | }
360 | ],
361 | "annotations": {
362 | ```
363 |
364 | ## Create multi-arch image / fat-manifest
365 |
366 | ```
367 | [root@x86-instance multi-arch]# podman manifest create localhost/demo
368 | 0deab136998a9b9143d5b253b1b6e8a6d741cfeb5fd9641379a4317ec117bc38
369 | [root@x86-instance multi-arch]# podman manifest add localhost/demo quay.io/openshift-examples/multi-arch:demo-x86_64
370 | 0deab136998a9b9143d5b253b1b6e8a6d741cfeb5fd9641379a4317ec117bc38
371 | [root@x86-instance multi-arch]# podman manifest add localhost/demo quay.io/openshift-examples/multi-arch:demo-aarch64
372 | 0deab136998a9b9143d5b253b1b6e8a6d741cfeb5fd9641379a4317ec117bc38
373 | [root@x86-instance multi-arch]# podman manifest push localhost/demo quay.io/openshift-examples/multi-arch:demo
374 | Getting image list signatures
375 | Copying 2 images generated from 2 images in list
376 | Copying image sha256:76535c50cab1708ff17dc67e93d2a06dea01978f7201d17fd6b28b32f8ce9555 (1/2)
377 | Getting image source signatures
378 | Copying blob 9e167103aefa skipped: already exists
379 | Copying blob bd9ddc54bea9 skipped: already exists
380 | Copying config 81b91103bc done |
381 | Writing manifest to image destination
382 | Copying image sha256:4eab20bcf7da10905cb95ce80141869e84854d15d99454e1365f10286d519f62 (2/2)
383 | Getting image source signatures
384 | Copying blob bd9ddc54bea9 skipped: already exists
385 | Copying blob 76f837f08b76 skipped: already exists
386 | Copying config 01d89888b7 done |
387 | Writing manifest to image destination
388 | Writing manifest list to image destination
389 | Storing list signatures
390 | [root@x86-instance multi-arch]# podman images --digests --no-trunc
391 | REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
392 | localhost/demo latest sha256:20b959ad5960230b65a77b746bdbf5d991ade4d7a129c2554e167acdcc990531 sha256:0deab136998a9b9143d5b253b1b6e8a6d741cfeb5fd9641379a4317ec117bc38 6 minutes ago 833 B
393 | quay.io/openshift-examples/multi-arch demo-x86_64 sha256:66ade3f15bca773a0227d4ff479bb1191b5e5bb94da88bab7307284129bb1733 sha256:81b91103bcad946edabad074db3e3eefcbfccd307587b6b40257bb0932a31705 24 minutes ago 26.1 MB
394 | registry.access.redhat.com/ubi9/ubi-micro latest sha256:bd93cff066cc579e49d53f50782f7edad319031e9d511b1e8709cf16be8d78a0 sha256:1b9d4f56fb2cd4401fa14437e3f245e6872388ed3e50f72926234315cbf4f817 3 weeks ago 26.1 MB
395 |
396 | ```
397 |
398 |
399 | Question: How to predict the Image ID (`6270f63fbb1c`) of the manifest?
400 |
401 | Red Hat internal slack #forum-container-engines: https://redhat-internal.slack.com/archives/CBBJY9GSX/p1696249069114529
402 |
403 | ```
404 | [root@x86-instance storage]# podman manifest create localhost/demo2
405 | 6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c
406 | [root@x86-instance storage]# podman images --digests --no-trunc
407 | REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
408 | localhost/demo2 latest sha256:20b959ad5960230b65a77b746bdbf5d991ade4d7a129c2554e167acdcc990531 sha256:6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c 20 seconds ago 110 B
409 | [root@x86-instance storage]# cat ./overlay-images/6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c/manifest
410 | {"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","manifests":null}[root@x86-instance storage]# cat ./overlay-images/6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c/manifest | sha256sum
411 | 20b959ad5960230b65a77b746bdbf5d991ade4d7a129c2554e167acdcc990531 -
412 | [root@x86-instance storage]# pwd
413 | /var/lib/containers/storage
414 | [root@x86-instance storage]# cat overlay-images/images.json | jq
415 | ..
416 | {
417 | "id": "6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c",
418 | "digest": "sha256:20b959ad5960230b65a77b746bdbf5d991ade4d7a129c2554e167acdcc990531",
419 | "names": [
420 | "localhost/demo2:latest"
421 | ],
422 | "big-data-names": [
423 | "manifest",
424 | "instances.json"
425 | ],
426 | "big-data-sizes": {
427 | "instances.json": 2,
428 | "manifest": 108
429 | },
430 | "big-data-digests": {
431 | "instances.json": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
432 | "manifest": "sha256:20b959ad5960230b65a77b746bdbf5d991ade4d7a129c2554e167acdcc990531"
433 | },
434 | "created": "2023-10-01T20:03:26.300473396Z"
435 | }
436 |
437 | ..
438 |
439 |
440 | [root@x86-instance storage]# find | grep 6270
441 | ./overlay-images/6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c
442 | ./overlay-images/6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c/manifest
443 | ./overlay-images/6270f63fbb1c4ae4b18c82936f5be0c6523e77455a2565ee48013807b813a08c/instances.json
444 |
445 |
446 | ```
447 |
448 |
449 |
450 |
451 | ## Discover via quay.io web ui
452 |
453 |
454 |
455 | 
456 |
457 | ## Discover via explore.ggcr.dev
458 |
459 |
460 |
461 |
462 | ## Copy & Muli-Arch image and discover
463 |
464 | Deploy a registry, for example:
465 |
466 |
467 |
468 | Copy image into registry:
469 |
470 | ```bash
471 | export REGISTRY=registry-multi-arch-demo.apps....
472 |
473 | skopeo copy --all \
474 | docker://quay.io/openshift-examples/multi-arch:demo \
475 | docker://${REGISTRY}/openshift-examples/multi-arch:demo
476 |
477 | # Optional - just the tags, blobs already copied.
478 | skopeo copy --all \
479 | docker://quay.io/openshift-examples/multi-arch:demo-x86_64 \
480 | docker://${REGISTRY}/openshift-examples/multi-arch:demo-x86_64
481 | skopeo copy --all \
482 | docker://quay.io/openshift-examples/multi-arch:demo-aarch64 \
483 | docker://${REGISTRY}/openshift-examples/multi-arch:demo-aarch64
484 |
485 | ```
486 |
487 | Optional, set registry read-only:
488 | ```bash =""
489 | oc patch deployment/registry -p '{"spec":{"template":{"spec":{"containers":[{"name":"registry","env":[{"name":"REGISTRY_STORAGE_MAINTENANCE_READONLY","value":"{\"enabled\":true}"}]}]}}}}'
490 | ```
491 |
492 | ### Take a look into the registry
493 |
494 | [](https://www.youtube.com/watch?v=v_v1OhRcOZU)
495 |
496 |
497 | `oc rsh -c tools deployment/registry`:
498 |
499 | For example, double check the sha256 change
500 |
501 | ```bash
502 | sh-4.4# cd /registry/docker/registry/v2/blobs/sha256/76/76f837f08b7667f5c10d53f91ca4885797a2cfa13f195e9bd024ad9ad934d0d2/
503 | sh-4.4# file *
504 | data: gzip compressed data, original size 27290112
505 |
506 | sh-4.4# cp data foo.gz
507 | sh-4.4# gzip -d foo.gz
508 | sh-4.4# sha256sum *
509 | 76f837f08b7667f5c10d53f91ca4885797a2cfa13f195e9bd024ad9ad934d0d2 data
510 | 791a6a33d694bf7f1a8a1373b17e2cead2c0e2ee17620cd64128acfa88d2a953 foo
511 | sh-4.4#
512 | ```
513 |
514 | ## Multi-arch build
515 |
516 | ### via Podman Desktop or on Fedora Linux
517 |
518 | ```bash
519 | export IMAGE='quay.io/openshift-examples/multi-arch:podman-desktop-example'
520 | podman build --platform linux/amd64,linux/arm64 --manifest ${IMAGE} .
521 | podman manifest inspect ${IMAGE}
522 | podman manifest push ${IMAGE}
523 | skopeo inspect --raw docker://${IMAGE} | jq
524 | ```
525 |
526 | ### via GitHub Actions
527 |
528 | Example: https://github.com/rbo/antora-viewer
529 |
530 | ```yaml
531 | jobs:
532 | cicd:
533 | runs-on: ubuntu-latest
534 | steps:
535 | - name: checkout
536 | uses: actions/checkout@v4
537 | - name: set datetime
538 | run: |
539 | echo "datetime=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
540 | - name: Install qemu dependency
541 | run: |
542 | sudo apt-get update
543 | sudo apt-get install -y qemu-user-static
544 | - name: build image
545 | id: build-image
546 | uses: redhat-actions/buildah-build@v2
547 | with:
548 | image: ${{ github.repository }}
549 | tags: latest ${{ github.ref_name }}
550 | platforms: linux/amd64, linux/arm64
551 | context: ./container
552 | containerfiles: |
553 | ./container/Containerfile
554 | build-args: |
555 | CREATED_AT=${{ env.datetime }}
556 | GITHUB_SHA=${{ github.sha }}
557 | - name: push image to ghcr.io
558 | uses: redhat-actions/push-to-registry@v2
559 | with:
560 | image: ${{ steps.build-image.outputs.image }}
561 | tags: ${{ steps.build-image.outputs.tags }}
562 | registry: ghcr.io
563 | username: ${{ github.actor }}
564 | password: ${{ secrets.GITHUB_TOKEN }}
565 | ```
566 |
--------------------------------------------------------------------------------