<h1>Goal</h1>

<p>Build a CI/CD pipeline multiple GitLab repositories with a certain project structure can make use of. For this, a Docker container with Python code is built and subsequently securely pushed to Google Cloud's Container Registry.</p>

<h1>Set up</h1>

<ul>
<li>KubernetesExecutor is installed on Kubernetes Engine using the <a href="https://docs.gitlab.com/runner/install/kubernetes.html" rel="nofollow noreferrer">Helm chart</a> as provided by GitLab.</li>
<li>The base image for the build process (<code>runners.image</code> in the <code>values.yaml</code>) is a custom one as this helps automatically containerising the provided repository. <strong>The reason this is worth mentioning is that this is from the <em>same</em> private repository as where the image should be pushed to.</strong></li>
<li>Right now, building the container from the repository runs successfully (see code below).</li>
</ul>

<h1>Problem</h1>

<p>How can I <em>push</em> the image to the Container Registry <em>without</em> adding a service account key to a Docker image (otherwise, please convince me this isn't bad practice)?</p>

<h1>Code</h1>

<h2>.gitlab-ci.yml</h2>

<pre class="lang-yaml prettyprint-override"><code>services:
  - docker:19.03.1-dind

stages:
  - build

build:
  stage: build
  script:
    - docker build -t ${CONTAINER_REGISTRY}/pyton-container-test:latest .
    # This line is where I'd need to use `docker login`, I guess.
    - docker push ${CONTAINER_REGISTRY}/python-container-test:latest
</code></pre>

<h2>values.yaml (Helm)</h2>

<p>It's worth mentioning that the following environment variables are set by the GitLab Runner:</p>

<pre class="lang-yaml prettyprint-override"><code>runners:
  env:
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: tcp://localhost:2375
    DOCKER_TLS_CERTDIR: ""
    CONTAINER_REGISTRY: eu.gcr.io/&lt;project_id&gt;
</code></pre>

<h1>Direction of solution</h1>

<p>I think I should be able to mount a secret from the Kubernetes cluster to the GitLab Runner build pod, but I can't seem to find a way to do that. Then, I should be able to add the following line into <code>.gitlab-ci.yml</code>:</p>

<pre class="lang-sh prettyprint-override"><code>cat mounted_secret.json | docker login -u _json_key --password-stdin https://eu.gcr.io
</code></pre>

<p>Setting up <code>config.toml</code> to use a <a href="https://docs.gitlab.com/runner/executors/kubernetes.html#secret-volumes" rel="nofollow noreferrer">secret volume</a> should work. However, with a Helm chart this doesn't seem possible yet.</p>

<h1>Notes</h1>

<ul>
<li>It <em>is</em> possible to set protected environment variables in GitLab CI, but I'd rather not, as they're harder to maintain.</li>
<li>I've investigated <a href="https://stackoverflow.com/questions/52474255/gitlab-runner-image-with-gcp-credentials">this</a> answer, but this says I need to add a key to my Docker image.</li>
<li>Looked into the <a href="https://docs.gitlab.com/runner/configuration/advanced-configuration.html#using-a-private-container-registry" rel="nofollow noreferrer">GitLab documentation</a> on using a private container registry, but don't seem to get much further with that.</li>
<li>A similar problem would occur when, for example, it must connect to a database during the build process.</li>
</ul>

<p>You can add <code>DOCKER_AUTH_CONFIG</code> CI/CD variable with auth values from <code>~/.docker/config.json</code>. The variable will look like this:</p>
<pre><code>{
    &quot;auths&quot;: {
        &quot;northamerica-northeast1-docker.pkg.dev&quot;: {
            &quot;auth&quot;: &quot;{JSON key here}&quot;
        },
        &quot;us.gcr.io&quot;: {
            &quot;auth&quot;: &quot;{JSON key here}&quot;
        }
    },
    &quot;HttpHeaders&quot;: {
        &quot;User-Agent&quot;: &quot;Docker-Client/19.03.13 (linux)&quot;
    }
}
</code></pre>

<p>This way, next time your gitlab runner is trying to pull a docker image from private repo, it will be able to do so.</p>
