build: use multi-stage dockerfile (#1054)

Signed-off-by: Mohammed Naser <mnaser@vexxhost.com>
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..1cf987f
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,125 @@
+FROM ubuntu:jammy-20240227 AS ubuntu
+LABEL org.opencontainers.image.source=https://github.com/vexxhost/atmosphere
+
+FROM ubuntu AS ubuntu-cloud-archive
+ADD --chmod=644 https://git.launchpad.net/ubuntu/+source/ubuntu-keyring/plain/keyrings/ubuntu-cloud-keyring.gpg /etc/apt/trusted.gpg.d/ubuntu-cloud-keyring.gpg
+ARG RELEASE
+RUN <<EOF bash -xe
+source /etc/os-release
+if [ "\${VERSION_CODENAME}" = "jammy" ]; then \
+    if [ "${RELEASE}" = "yoga" ]; then \
+        # NOTE: Yoga shipped with 22.04, so no need to add an extra repository.
+        echo "" > /etc/apt/sources.list.d/cloudarchive.list; \
+    elif [ "${RELEASE}" = "zed" ]; then \
+        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/${RELEASE} main" > /etc/apt/sources.list.d/cloudarchive.list; \
+    elif [ "${RELEASE}" = "2023.1" ]; then \
+        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/antelope main" > /etc/apt/sources.list.d/cloudarchive.list; \
+    elif [ "${RELEASE}" = "2023.2" ]; then \
+        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/bobcat main" > /etc/apt/sources.list.d/cloudarchive.list; \
+    elif [ "${RELEASE}" = "master" ]; then \
+        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/caracal main" > /etc/apt/sources.list.d/cloudarchive.list; \
+    else \
+        echo "${RELEASE} is not supported on \${VERSION_CODENAME}"; \
+        exit 1; \
+    fi; \
+else
+    echo "Unsupported release"; \
+    exit 1; \
+fi
+EOF
+
+FROM alpine/git AS requirements
+ARG BRANCH
+ADD https://opendev.org/openstack/requirements.git#${BRANCH} /src
+RUN <<EOF sh -xe
+sed -i 's/cryptography===36.0.2/cryptography===42.0.4/' /src/upper-constraints.txt
+sed -i 's/cryptography===40.0.2/cryptography===42.0.4/' /src/upper-constraints.txt
+sed -i 's/cryptography===41.0.7/cryptography===42.0.4/' /src/upper-constraints.txt
+sed -i 's/Django===3.2.18/Django===3.2.24/' /src/upper-constraints.txt
+sed -i 's/Flask===2.2.3/Flask===2.2.5/' /src/upper-constraints.txt
+sed -i 's/Jinja2===3.1.2/Jinja2===3.1.3/' /src/upper-constraints.txt
+sed -i 's/oauthlib===3.2.0/oauthlib===3.2.2/' /src/upper-constraints.txt
+sed -i 's/paramiko===2.11.0/paramiko===3.4.0/' /src/upper-constraints.txt
+sed -i 's/paramiko===3.1.0/paramiko===3.4.0/' /src/upper-constraints.txt
+sed -i 's/protobuf===4.21.5/protobuf===4.21.6/' /src/upper-constraints.txt
+sed -i 's/pyOpenSSL===22.0.0/pyOpenSSL===24.0.0/' /src/upper-constraints.txt
+sed -i 's/pyOpenSSL===23.1.1/pyOpenSSL===24.0.0/' /src/upper-constraints.txt
+sed -i 's/requests===2.28.1/requests===2.31.0/' /src/upper-constraints.txt
+sed -i 's/requests===2.28.2/requests===2.31.0/' /src/upper-constraints.txt
+sed -i 's/sqlparse===0.4.2/sqlparse===0.4.4/' /src/upper-constraints.txt
+sed -i 's/urllib3===1.26.12/urllib3===1.26.18/' /src/upper-constraints.txt
+sed -i 's/urllib3===1.26.15/urllib3===1.26.18/' /src/upper-constraints.txt
+sed -i 's/Werkzeug===2.2.2/Werkzeug===2.3.8/' /src/upper-constraints.txt
+sed -i 's/Werkzeug===2.2.3/Werkzeug===2.3.8/' /src/upper-constraints.txt
+sed -i 's/zstd===1.5.2.5/zstd===1.5.4.0/' /src/upper-constraints.txt
+sed -i '/glance-store/d' /src/upper-constraints.txt
+sed -i '/horizon/d' /src/upper-constraints.txt
+EOF
+
+FROM ubuntu-cloud-archive AS openstack-venv-builder
+RUN <<EOF bash -xe
+apt-get update -qq
+apt-get install -qq -y --no-install-recommends \
+    build-essential \
+    git \
+    libldap2-dev \
+    libpcre3-dev \
+    libsasl2-dev \
+    libssl-dev \
+    lsb-release \
+    openssh-client \
+    python3 \
+    python3-dev \
+    python3-pip \
+    python3-venv
+EOF
+RUN <<EOF bash -xe
+python3 -m venv --upgrade-deps --system-site-packages /var/lib/openstack
+EOF
+ENV PATH=/var/lib/openstack/bin:$PATH
+COPY --link --from=requirements /src/upper-constraints.txt /upper-constraints.txt
+RUN <<EOF bash -xe
+pip3 install \
+    --constraint /upper-constraints.txt \
+        cryptography \
+        pymysql \
+        python-binary-memcached \
+        python-memcached \
+        uwsgi
+EOF
+
+FROM ubuntu-cloud-archive AS openstack-runtime
+RUN <<EOF bash -xe
+apt-get update -qq
+apt-get install -qq -y --no-install-recommends \
+    ca-certificates \
+    libpython3.10 \
+    lsb-release \
+    python3-distutils \
+    sudo
+EOF
+ARG PROJECT
+ARG SHELL=/usr/sbin/nologin
+RUN \
+    groupadd -g 42424 ${PROJECT} && \
+    useradd -u 42424 -g 42424 -M -d /var/lib/${PROJECT} -s ${SHELL} -c "${PROJECT} User" ${PROJECT} && \
+    mkdir -p /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT} && \
+    chown -Rv ${PROJECT}:${PROJECT} /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT}
+ENV PATH=/var/lib/openstack/bin:$PATH
+
+FROM alpine/git AS barbican-src
+ARG BARBICAN_GIT_REF
+ADD --keep-git-dir=true https://opendev.org/openstack/barbican.git#${BARBICAN_GIT_REF} /src
+RUN git -C /src fetch --unshallow
+
+FROM openstack-venv-builder AS barbican-build
+COPY --from=barbican-src --link /src /src/barbican
+RUN <<EOF bash -xe
+pip3 install \
+    --constraint /upper-constraints.txt \
+        /src/barbican \
+        pykmip
+EOF
+
+FROM openstack-runtime AS barbican
+COPY --from=barbican-build --link /var/lib/openstack /var/lib/openstack
diff --git a/docker-bake.hcl b/docker-bake.hcl
index 5094d56..ea8a9be 100644
--- a/docker-bake.hcl
+++ b/docker-bake.hcl
@@ -20,144 +20,11 @@
     result = PUSH_TO_CACHE ? [format("%s,%s", cache_from(image)[0], "mode=max,image-manifest=true,oci-mediatypes=true,compression=zstd")] : []
 }
 
-target "ubuntu" {
-    context = "./images/ubuntu"
-
-    cache-from = cache_from("ubuntu")
-    cache-to = cache_to("ubuntu")
-
-    contexts = {
-        ubuntu = "docker-image://ubuntu:jammy-20240227"
-    }
-}
-
-target "git" {
-    context = "./images/git"
-
-    cache-from = cache_from("git")
-    cache-to = cache_to("git")
-}
-
-target "ubuntu-cloud-archive" {
-    name = "ubuntu-cloud-archive-${release.tgt}"
-    context = "./images/ubuntu-cloud-archive"
-
-    cache-from = cache_from("ubuntu-cloud-archive:${release.name}")
-    cache-to = cache_to("ubuntu-cloud-archive:${release.name}")
-
-    matrix = {
-        release = [
-            {
-                tgt = "zed",
-                name = "zed",
-            },
-            {
-                tgt = "bobcat",
-                name = "2023.2",
-            }
-        ]
-    }
-
-    contexts = {
-        ubuntu = "target:ubuntu"
-    }
-
-    args = {
-        RELEASE = release.name
-    }
-}
-
-target "requirements" {
-    name = "requirements-${release.tgt}"
-    context = "./images/requirements"
-
-    cache-from = cache_from("requirements:${release.name}")
-    cache-to = cache_to("requirements:${release.name}")
-
-    matrix = {
-        release = [
-            {
-                tgt = "zed",
-                name = "zed",
-            },
-            {
-                tgt = "bobcat",
-                name = "2023.2",
-            }
-        ]
-    }
-
-    contexts = {
-        ubuntu = "target:ubuntu"
-    }
-
-    args = {
-        RELEASE = release.name
-    }
-}
-
-target "openstack-venv-builder" {
-    name = "openstack-venv-builder-${release.tgt}"
-    context = "./images/openstack-venv-builder"
-
-    cache-from = cache_from("openstack-venv-builder:${release.name}")
-    cache-to = cache_to("openstack-venv-builder:${release.name}")
-
-    matrix = {
-        release = [
-            {
-                tgt = "zed",
-                name = "zed",
-            },
-            {
-                tgt = "bobcat",
-                name = "2023.2",
-            }
-        ]
-    }
-
-    contexts = {
-        ubuntu-cloud-archive = "target:ubuntu-cloud-archive-${release.tgt}",
-        requirements = "target:requirements-${release.tgt}",
-    }
-
-    args = {
-        RELEASE = release.name
-    }
-}
-
-target "openstack-runtime" {
-    name = "openstack-runtime-${release.tgt}"
-    context = "./images/openstack-runtime"
-
-    cache-from = cache_from("openstack-runtime:${release.name}")
-    cache-to = cache_to("openstack-runtime:${release.name}")
-
-    matrix = {
-        release = [
-            {
-                tgt = "zed",
-                name = "zed",
-            },
-            {
-                tgt = "bobcat",
-                name = "2023.2",
-            }
-        ]
-    }
-
-    contexts = {
-        ubuntu-cloud-archive = "target:ubuntu-cloud-archive-${release.tgt}",
-    }
-
-    args = {
-        RELEASE = release.name
-    }
-}
-
 target "barbican" {
     name = "barbican-${release.tgt}"
-    context = "./images/barbican"
+
+    context = "."
+    target = "barbican"
 
     cache-from = cache_from("barbican:${release.name}")
     cache-to = cache_to("barbican:${release.name}")
@@ -177,14 +44,9 @@
         ]
     }
 
-    contexts = {
-        openstack-venv-builder = "target:openstack-venv-builder-${release.tgt}"
-        openstack-runtime = "target:openstack-runtime-${release.tgt}",
-        git = "target:git"
-    }
-
     args = {
         RELEASE = release.name
+        BRANCH = format("stable/%s", release.name)
         PROJECT = "barbican"
         BARBICAN_GIT_REF = release.ref
     }
diff --git a/images/barbican/Dockerfile b/images/barbican/Dockerfile
deleted file mode 100644
index 243df60..0000000
--- a/images/barbican/Dockerfile
+++ /dev/null
@@ -1,16 +0,0 @@
-FROM git AS barbican
-ARG BARBICAN_GIT_REF
-ADD --keep-git-dir=true https://opendev.org/openstack/barbican.git#${BARBICAN_GIT_REF} /src
-RUN git fetch --unshallow
-
-FROM openstack-venv-builder AS build
-COPY --from=barbican --link /src /src/barbican
-RUN <<EOF bash -xe
-pip3 install \
-    --constraint /upper-constraints.txt \
-        /src/barbican \
-        pykmip
-EOF
-
-FROM openstack-runtime
-COPY --from=build --link /var/lib/openstack /var/lib/openstack
diff --git a/images/git/Dockerfile b/images/git/Dockerfile
deleted file mode 100644
index af8b7e4..0000000
--- a/images/git/Dockerfile
+++ /dev/null
@@ -1,2 +0,0 @@
-FROM alpine/git:latest
-WORKDIR /src
diff --git a/images/openstack-runtime/Dockerfile b/images/openstack-runtime/Dockerfile
deleted file mode 100644
index 732761d..0000000
--- a/images/openstack-runtime/Dockerfile
+++ /dev/null
@@ -1,19 +0,0 @@
-FROM ubuntu-cloud-archive
-RUN <<EOF bash -xe
-apt-get update -qq
-apt-get install -qq -y --no-install-recommends \
-    ca-certificates \
-    libpython3.10 \
-    lsb-release \
-    python3-distutils \
-    sudo
-EOF
-
-ONBUILD ARG PROJECT
-ONBUILD ARG SHELL=/usr/sbin/nologin
-ONBUILD RUN \
-    groupadd -g 42424 ${PROJECT} && \
-    useradd -u 42424 -g 42424 -M -d /var/lib/${PROJECT} -s ${SHELL} -c "${PROJECT} User" ${PROJECT} && \
-    mkdir -p /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT} && \
-    chown -Rv ${PROJECT}:${PROJECT} /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT}
-ONBUILD ENV PATH=/var/lib/openstack/bin:$PATH
diff --git a/images/openstack-venv-builder/Dockerfile b/images/openstack-venv-builder/Dockerfile
deleted file mode 100644
index 7fea169..0000000
--- a/images/openstack-venv-builder/Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-FROM ubuntu-cloud-archive
-RUN <<EOF bash -xe
-apt-get update -qq
-apt-get install -qq -y --no-install-recommends \
-    build-essential \
-    git \
-    libldap2-dev \
-    libpcre3-dev \
-    libsasl2-dev \
-    libssl-dev \
-    lsb-release \
-    openssh-client \
-    python3 \
-    python3-dev \
-    python3-pip \
-    python3-venv
-EOF
-RUN <<EOF bash -xe
-python3 -m venv --upgrade-deps --system-site-packages /var/lib/openstack
-EOF
-ENV PATH=/var/lib/openstack/bin:$PATH
-COPY --link --from=requirements /src/upper-constraints.txt /upper-constraints.txt
-RUN <<EOF bash -xe
-pip3 install \
-    --constraint /upper-constraints.txt \
-        cryptography \
-        pymysql \
-        python-binary-memcached \
-        python-memcached \
-        uwsgi
-EOF
diff --git a/images/requirements/Dockerfile b/images/requirements/Dockerfile
deleted file mode 100644
index 1ba9f82..0000000
--- a/images/requirements/Dockerfile
+++ /dev/null
@@ -1,41 +0,0 @@
-FROM ubuntu
-RUN <<EOF bash -xe
-apt-get update -qq
-apt-get install -qq -y --no-install-recommends ca-certificates git
-EOF
-
-ARG RELEASE
-RUN <<EOF bash -xe
-BRANCH=stable/${RELEASE}
-if [ "${RELEASE}" = "master" ]; then
-    BRANCH=master
-fi
-
-git clone --branch \$BRANCH https://github.com/openstack/requirements /src
-EOF
-
-RUN <<EOF sh -xe
-sed -i 's/cryptography===36.0.2/cryptography===42.0.4/' /src/upper-constraints.txt
-sed -i 's/cryptography===40.0.2/cryptography===42.0.4/' /src/upper-constraints.txt
-sed -i 's/cryptography===41.0.7/cryptography===42.0.4/' /src/upper-constraints.txt
-sed -i 's/Django===3.2.18/Django===3.2.24/' /src/upper-constraints.txt
-sed -i 's/Flask===2.2.3/Flask===2.2.5/' /src/upper-constraints.txt
-sed -i 's/Jinja2===3.1.2/Jinja2===3.1.3/' /src/upper-constraints.txt
-sed -i 's/oauthlib===3.2.0/oauthlib===3.2.2/' /src/upper-constraints.txt
-sed -i 's/paramiko===2.11.0/paramiko===3.4.0/' /src/upper-constraints.txt
-sed -i 's/paramiko===3.1.0/paramiko===3.4.0/' /src/upper-constraints.txt
-sed -i 's/protobuf===4.21.5/protobuf===4.21.6/' /src/upper-constraints.txt
-sed -i 's/pyOpenSSL===22.0.0/pyOpenSSL===24.0.0/' /src/upper-constraints.txt
-sed -i 's/pyOpenSSL===23.1.1/pyOpenSSL===24.0.0/' /src/upper-constraints.txt
-sed -i 's/requests===2.28.1/requests===2.31.0/' /src/upper-constraints.txt
-sed -i 's/requests===2.28.2/requests===2.31.0/' /src/upper-constraints.txt
-sed -i 's/sqlparse===0.4.2/sqlparse===0.4.4/' /src/upper-constraints.txt
-sed -i 's/urllib3===1.26.12/urllib3===1.26.18/' /src/upper-constraints.txt
-sed -i 's/urllib3===1.26.15/urllib3===1.26.18/' /src/upper-constraints.txt
-sed -i 's/Werkzeug===2.2.2/Werkzeug===2.3.8/' /src/upper-constraints.txt
-sed -i 's/Werkzeug===2.2.3/Werkzeug===2.3.8/' /src/upper-constraints.txt
-sed -i 's/zstd===1.5.2.5/zstd===1.5.4.0/' /src/upper-constraints.txt
-
-sed -i '/glance-store/d' /src/upper-constraints.txt
-sed -i '/horizon/d' /src/upper-constraints.txt
-EOF
diff --git a/images/ubuntu-cloud-archive/Dockerfile b/images/ubuntu-cloud-archive/Dockerfile
deleted file mode 100644
index 31ab98e..0000000
--- a/images/ubuntu-cloud-archive/Dockerfile
+++ /dev/null
@@ -1,28 +0,0 @@
-FROM ubuntu
-COPY trusted.gpg.d/* /etc/apt/trusted.gpg.d/
-
-ARG RELEASE
-RUN <<EOF bash -xe
-source /etc/os-release
-
-if [ "\${VERSION_CODENAME}" = "jammy" ]; then \
-    if [ "${RELEASE}" = "yoga" ]; then \
-        # NOTE: Yoga shipped with 22.04, so no need to add an extra repository.
-        echo "" > /etc/apt/sources.list.d/cloudarchive.list; \
-    elif [ "${RELEASE}" = "zed" ]; then \
-        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/${RELEASE} main" > /etc/apt/sources.list.d/cloudarchive.list; \
-    elif [ "${RELEASE}" = "2023.1" ]; then \
-        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/antelope main" > /etc/apt/sources.list.d/cloudarchive.list; \
-    elif [ "${RELEASE}" = "2023.2" ]; then \
-        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/bobcat main" > /etc/apt/sources.list.d/cloudarchive.list; \
-    elif [ "${RELEASE}" = "master" ]; then \
-        echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/caracal main" > /etc/apt/sources.list.d/cloudarchive.list; \
-    else \
-        echo "${RELEASE} is not supported on \${VERSION_CODENAME}"; \
-        exit 1; \
-    fi; \
-else
-    echo "Unsupported release"; \
-    exit 1; \
-fi
-EOF
diff --git a/images/ubuntu-cloud-archive/trusted.gpg.d/cloud-archive.gpg b/images/ubuntu-cloud-archive/trusted.gpg.d/cloud-archive.gpg
deleted file mode 100644
index f902962..0000000
--- a/images/ubuntu-cloud-archive/trusted.gpg.d/cloud-archive.gpg
+++ /dev/null
Binary files differ
diff --git a/images/ubuntu/Dockerfile b/images/ubuntu/Dockerfile
deleted file mode 100644
index d776231..0000000
--- a/images/ubuntu/Dockerfile
+++ /dev/null
@@ -1,2 +0,0 @@
-FROM ubuntu
-LABEL org.opencontainers.image.source=https://github.com/vexxhost/atmosphere