Skip to content

Commit 8264314

Browse files
Robert Marshallbalasankarc
andcommitted
Merge branch 'docker-buildx-helper' into 'master'
Add foundation to build multiarch images Closes #8469 and #8470 See merge request https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/7492 Merged-by: Robert Marshall <[email protected]> Approved-by: Dmytro Makovey <[email protected]> Approved-by: Robert Marshall <[email protected]> Reviewed-by: Robert Marshall <[email protected]> Co-authored-by: Balasankar 'Balu' C <[email protected]>
2 parents a068eb2 + ca02e0c commit 8264314

File tree

10 files changed

+309
-32
lines changed

10 files changed

+309
-32
lines changed

docker/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ ENV LANG=C.UTF-8
1010
COPY locale.gen /etc/locale.gen
1111

1212
# Install required packages
13+
# Note: libatomic1 is only required for arm64, but it is small enough to not
14+
# bother about the conditional inclusion logic
1315
RUN apt-get update -q \
1416
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
1517
busybox \
@@ -20,6 +22,7 @@ RUN apt-get update -q \
2022
wget \
2123
perl \
2224
libperl5.34 \
25+
libatomic1 \
2326
&& locale-gen \
2427
&& cp -a /usr/lib/locale/locale-archive /tmp/locale-archive \
2528
&& DEBIAN_FRONTEND=noninteractive apt-get purge -yq locales \
@@ -43,6 +46,8 @@ RUN ln -fs /dev/null /run/motd.dynamic
4346
# Legacy code to be removed on 17.0. See: https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/7035
4447
ENV GITLAB_ALLOW_SHA1_RSA=false
4548

49+
ARG TARGETARCH
50+
4651
# Copy assets
4752
COPY RELEASE /
4853
COPY assets/ /assets/

docker/assets/setup

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,19 @@ source /RELEASE
1010
sed -i "/DOWNLOAD_URL/d;/CI_JOB_TOKEN/d;" /RELEASE
1111

1212
# Install GitLab
13+
if [[ "${TARGETARCH}" == "amd64" ]]; then
14+
export DOWNLOAD_URL=${DOWNLOAD_URL_amd64}
15+
elif [[ "${TARGETARCH}" == "arm64" ]]; then
16+
export DOWNLOAD_URL=${DOWNLOAD_URL_arm64}
17+
else
18+
echo "Unknown TARGETARCH: DOWNLOAD_URL not set"
19+
fi
20+
1321
DOWNLOAD_URL=${DOWNLOAD_URL} CI_JOB_TOKEN=${CI_JOB_TOKEN} /assets/download-package && dpkg -i /tmp/gitlab.deb
1422
rm -rf /tmp/gitlab.deb /var/lib/apt/lists/*
1523

24+
unset DOWNLOAD_URL_amd64
25+
unset DOWNLOAD_URL_arm64
1626
unset DOWNLOAD_URL
1727
unset CI_JOB_TOKEN
1828

gitlab-ci-config/dev-gitlab-org.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ Ubuntu-22.04-arm64-branch:
315315
- !reference [.default_rules, rules]
316316
- if: '$PIPELINE_TYPE =~ /_(NIGHTLY|BRANCH)_BUILD_PIPELINE$/'
317317
- if: '$PIPELINE_TYPE =~ /TRIGGERED_(CE|EE)_PIPELINE/'
318+
# TODO: When multi-arch images are built by default, make this an
319+
# automatic job
318320
when: manual
319321
allow_failure: true
320322
CentOS-7-branch:

lib/gitlab/build/image.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ def copy_image_to_dockerhub(final_tag)
5151
SkopeoHelper.copy_image(source, target)
5252
end
5353

54+
def copy_image_to_gitlab_registry(final_tag)
55+
source = source_image_address
56+
target = gitlab_registry_image_address(tag: final_tag)
57+
58+
SkopeoHelper.login('gitlab-ci-token', Gitlab::Util.get_env('CI_JOB_TOKEN'), Gitlab::Util.get_env('CI_REGISTRY'))
59+
60+
SkopeoHelper.copy_image(source, target)
61+
end
62+
5463
def source_image_address
5564
raise NotImplementedError
5665
end

lib/gitlab/build/info/docker.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@ def tag
1313

1414
def release_file_contents
1515
repo = Gitlab::Util.get_env('PACKAGECLOUD_REPO') # Target repository
16+
download_urls = {}.tap do |urls|
17+
urls[:amd64] = Build::Info::CI.package_download_url
18+
urls[:arm64] = Build::Info::CI.package_download_url(arch: 'arm64')
19+
end
1620

17-
download_url = Build::Info::CI.package_download_url
18-
raise "Unable to identify package download URL." unless download_url
21+
raise "Unable to identify package download URLs." if download_urls.empty?
1922

2023
contents = []
2124
contents << "PACKAGECLOUD_REPO=#{repo.chomp}\n" if repo && !repo.empty?
2225
contents << "RELEASE_PACKAGE=#{Build::Info::Package.name}\n"
2326
contents << "RELEASE_VERSION=#{Build::Info::Package.release_version}\n"
24-
contents << "DOWNLOAD_URL=#{download_url}\n"
27+
contents << "DOWNLOAD_URL_amd64=#{download_urls[:amd64]}\n"
28+
contents << "DOWNLOAD_URL_arm64=#{download_urls[:arm64]}\n"
2529
contents << "CI_JOB_TOKEN=#{Build::Info::CI.job_token}\n"
2630
contents.join
2731
end

lib/gitlab/docker_helper.rb

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
require 'open3'
2+
require_relative 'docker_operations'
3+
4+
# TODO: Deprecate DockerOperations
5+
class DockerHelper < DockerOperations
6+
class << self
7+
def authenticate(username: nil, password: nil, registry: nil)
8+
puts "Logging in to Docker registry"
9+
10+
stdout, stderr, status = Open3.popen3({}, *%W[docker login --username=#{username} --password-stdin #{registry}]) do |stdin, stdout, stderr, wait_thr|
11+
stdin.puts(password)
12+
stdin.close
13+
14+
[stdout.read, stderr.read, wait_thr.value]
15+
end
16+
17+
return if status.success?
18+
19+
puts "Failed to login to Docker registry."
20+
puts "Output is: #{stdout}"
21+
puts stderr
22+
Kernel.exit 1
23+
end
24+
25+
# TODO: When multi-arch images are built by default, modify `platforms`
26+
# array to include `linux/arm64` also
27+
def build(location, image, tag, dockerfile: nil, buildargs: nil, platforms: %w[linux/amd64], push: true)
28+
create_builder
29+
30+
commands = %W[docker buildx build #{location} -t #{image}:#{tag}]
31+
32+
if (env_var_platforms = Gitlab::Util.get_env('DOCKER_BUILD_PLATFORMS'))
33+
platforms.append(env_var_platforms.split(",").map(&:strip))
34+
end
35+
36+
platforms.uniq!
37+
38+
commands += %W[--platform=#{platforms.join(',')}]
39+
40+
# If specified to push, we must push to registry. Even if not, if the
41+
# image being built is multiarch, we must push to registry.
42+
commands += %w[--push] if push || platforms.length > 1
43+
44+
commands += %W[-f #{dockerfile}] if dockerfile
45+
46+
buildargs&.each do |arg|
47+
commands += %W[--build-arg='#{arg}']
48+
end
49+
50+
puts "Running command: #{commands.join(' ')}"
51+
52+
Open3.popen2e(*commands) do |_, stdout_stderr, status|
53+
while line = stdout_stderr.gets
54+
puts line
55+
end
56+
57+
Kernel.exit 1 unless status.value.success?
58+
end
59+
end
60+
61+
def create_builder
62+
cleanup_existing_builder
63+
64+
puts "Creating docker builder instance"
65+
# TODO: For multi-arch builds, use Kubernetes driver for builder instance
66+
_, stdout_stderr, status = Open3.popen2e(*%w[docker buildx create --bootstrap --use --name omnibus-gitlab-builder])
67+
68+
return if status.value.success?
69+
70+
puts "Creating builder instance failed."
71+
puts "Output: #{stdout_stderr.read}"
72+
raise
73+
end
74+
75+
def cleanup_existing_builder
76+
puts "Cleaning any existing builder instances."
77+
_, _, status = Open3.popen2e(*%w[docker buildx ls | grep omnibus-gitlab-builder])
78+
unless status.value.success?
79+
puts "omnibus-gitlab-builder instance not found. Not attempting to clean."
80+
return
81+
end
82+
83+
_, stdout_stderr, status = Open3.popen2e(*%w[docker buildx rm --force omnibus-gitlab-builder])
84+
if status.value.success?
85+
puts "Successfully cleaned omnibus-gitlab-builder instance."
86+
else
87+
puts "Cleaning of omnibus-gitlab-builder instance failed."
88+
puts "Output: #{stdout_stderr.read}"
89+
end
90+
end
91+
end
92+
end

lib/gitlab/tasks/docker_tasks.rake

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ require_relative '../build/gitlab_image'
55
require_relative '../build/info/ci'
66
require_relative '../build/info/docker'
77
require_relative '../docker_operations'
8+
require_relative '../docker_helper'
89
require_relative '../util'
910

1011
namespace :docker do
@@ -14,11 +15,8 @@ namespace :docker do
1415
Gitlab::Util.section('docker:build:image') do
1516
Build::GitlabImage.write_release_file
1617
location = File.absolute_path(File.join(File.dirname(File.expand_path(__FILE__)), "../../../docker"))
17-
DockerOperations.build(
18-
location,
19-
Build::GitlabImage.gitlab_registry_image_address,
20-
'latest'
21-
)
18+
DockerHelper.authenticate(username: "gitlab-ci-token", password: Gitlab::Util.get_env("CI_JOB_TOKEN"), registry: Gitlab::Util.get_env('CI_REGISTRY'))
19+
DockerHelper.build(location, Build::GitlabImage.gitlab_registry_image_address, Build::Info::Docker.tag)
2220
end
2321
end
2422
end
@@ -28,11 +26,11 @@ namespace :docker do
2826
# Only runs on dev.gitlab.org
2927
task :staging do
3028
Gitlab::Util.section('docker:push:staging') do
31-
Build::GitlabImage.tag_and_push_to_gitlab_registry(Build::Info::Docker.tag)
32-
33-
# Also tag with CI_COMMIT_REF_SLUG so that manual testing using Docker
34-
# can use the same image name/tag.
35-
Build::GitlabImage.tag_and_push_to_gitlab_registry(Build::Info::CI.commit_ref_slug)
29+
# As part of build, the image is already tagged and pushed to GitLab
30+
# registry with `Build::Info::Docker.tag` as the tag. Also copy the
31+
# image with `CI_COMMIT_REF_SLUG` as the tag so that manual testing
32+
# using Docker can use the same image name/tag.
33+
Build::GitlabImage.copy_image_to_gitlab_registry(Build::Info::CI.commit_ref_slug)
3634
end
3735
end
3836

@@ -88,11 +86,11 @@ namespace :docker do
8886
desc "Push triggered Docker Image to GitLab Registry"
8987
task :triggered do
9088
Gitlab::Util.section('docker:push:triggered') do
91-
Build::GitlabImage.tag_and_push_to_gitlab_registry(Build::Info::Docker.tag)
92-
93-
# Also tag with CI_COMMIT_REF_SLUG so that manual testing using Docker
89+
# As part of build, the image is already tagged and pushed with
90+
# `Build::Info::Docker.tag` as the tag. Also copy the image with
91+
# `CI_COMMIT_REF_SLUG` as the tag so that manual testing using Docker
9492
# can use the same image name/tag.
95-
Build::GitlabImage.tag_and_push_to_gitlab_registry(Build::Info::CI.commit_ref_slug)
93+
Build::GitlabImage.copy_image_to_gitlab_registry(Build::Info::CI.commit_ref_slug)
9694
end
9795
end
9896
end

spec/lib/gitlab/build/image_spec.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ def self.dockerhub_image_name
109109
"PACKAGECLOUD_REPO=download-package",
110110
"RELEASE_PACKAGE=gitlab-ce",
111111
"RELEASE_VERSION=12.121.12-ce.0",
112-
"DOWNLOAD_URL=https://dev.gitlab.org/api/v4/projects/283/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ce_12.121.12-ce.0_amd64.deb",
112+
"DOWNLOAD_URL_amd64=https://dev.gitlab.org/api/v4/projects/283/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ce_12.121.12-ce.0_amd64.deb",
113+
"DOWNLOAD_URL_arm64=https://dev.gitlab.org/api/v4/projects/283/jobs/999999/artifacts/pkg/ubuntu-jammy_aarch64/gitlab-ce_12.121.12-ce.0_arm64.deb",
113114
"CI_JOB_TOKEN=NOT-CI-JOB-TOKEN\n"
114115
].join("\n")
115116
end
@@ -130,7 +131,8 @@ def self.dockerhub_image_name
130131
"PACKAGECLOUD_REPO=download-package",
131132
"RELEASE_PACKAGE=gitlab-ee",
132133
"RELEASE_VERSION=12.121.12-ee.0",
133-
"DOWNLOAD_URL=https://dev.gitlab.org/api/v4/projects/283/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ee_12.121.12-ee.0_amd64.deb",
134+
"DOWNLOAD_URL_amd64=https://dev.gitlab.org/api/v4/projects/283/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ee_12.121.12-ee.0_amd64.deb",
135+
"DOWNLOAD_URL_arm64=https://dev.gitlab.org/api/v4/projects/283/jobs/999999/artifacts/pkg/ubuntu-jammy_aarch64/gitlab-ee_12.121.12-ee.0_arm64.deb",
134136
"CI_JOB_TOKEN=NOT-CI-JOB-TOKEN\n"
135137
].join("\n")
136138
end
@@ -159,7 +161,8 @@ def self.dockerhub_image_name
159161
"PACKAGECLOUD_REPO=download-package",
160162
"RELEASE_PACKAGE=gitlab-ce",
161163
"RELEASE_VERSION=12.121.12-ce.0",
162-
"DOWNLOAD_URL=https://gitlab.com/api/v4/projects/20699/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ce_12.121.12-ce.0_amd64.deb",
164+
"DOWNLOAD_URL_amd64=https://gitlab.com/api/v4/projects/20699/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ce_12.121.12-ce.0_amd64.deb",
165+
"DOWNLOAD_URL_arm64=https://gitlab.com/api/v4/projects/20699/jobs/999999/artifacts/pkg/ubuntu-jammy_aarch64/gitlab-ce_12.121.12-ce.0_arm64.deb",
163166
"CI_JOB_TOKEN=NOT-CI-JOB-TOKEN\n"
164167
].join("\n")
165168
end
@@ -180,7 +183,8 @@ def self.dockerhub_image_name
180183
"PACKAGECLOUD_REPO=download-package",
181184
"RELEASE_PACKAGE=gitlab-ee",
182185
"RELEASE_VERSION=12.121.12-ee.0",
183-
"DOWNLOAD_URL=https://gitlab.com/api/v4/projects/20699/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ee_12.121.12-ee.0_amd64.deb",
186+
"DOWNLOAD_URL_amd64=https://gitlab.com/api/v4/projects/20699/jobs/999999/artifacts/pkg/ubuntu-jammy/gitlab-ee_12.121.12-ee.0_amd64.deb",
187+
"DOWNLOAD_URL_arm64=https://gitlab.com/api/v4/projects/20699/jobs/999999/artifacts/pkg/ubuntu-jammy_aarch64/gitlab-ee_12.121.12-ee.0_arm64.deb",
184188
"CI_JOB_TOKEN=NOT-CI-JOB-TOKEN\n"
185189
].join("\n")
186190
end

0 commit comments

Comments
 (0)