<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on despatches</title><link>https://icle.es/tags/docker/</link><description>Recent content in Docker on despatches</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 20 Jun 2025 09:25:00 +0100</lastBuildDate><atom:link href="https://icle.es/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>Build and push container image using bazel</title><link>https://icle.es/2025/06/06/bazel-go-docker-gcloud/</link><pubDate>Fri, 06 Jun 2025 13:06:14 +0000</pubDate><guid>https://icle.es/2025/06/06/bazel-go-docker-gcloud/</guid><description>&lt;p>I am building a small &lt;a href="https://icle.es/tags/golang">golang&lt;/a> &lt;a href="https://icle.es/tags/webapp">webapp&lt;/a>, and I want
to push a &lt;a href="https://icle.es/tags/oci">container&lt;/a> up for it, which can eventually be used in
Google Cloud Run, or elsewhere.&lt;/p>
&lt;p>In this post, I want to describe how I got it to push images build locally up to
googles artifact repository. It will include creating the artifac repository
using infrastructure as code&lt;/p>
&lt;p>The project is in a &lt;a href="https://icle.es/tags/monorepo">monorepo&lt;/a> that uses &lt;a href="https://icle.es/tags/bazel">bazel&lt;/a>.&lt;/p>
&lt;h2 id="the-executable-to-be-packaged">The executable to be packaged&lt;/h2>
```starlark
# //products/example/cmd/server/BUILD.bazel
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")

go_library(
 name = "server_lib",
 srcs = ["main.go"],
 visibility = ["//visibility:private"],
)

go_binary(
 name = "server",
 embed = [":server_lib"],
 visibility = ["//visibility:public"],
)
```</description><content:encoded><![CDATA[<p>I am building a small <a href="https://icle.es/tags/golang">golang</a> <a href="https://icle.es/tags/webapp">webapp</a>, and I want
to push a <a href="https://icle.es/tags/oci">container</a> up for it, which can eventually be used in
Google Cloud Run, or elsewhere.</p>
<p>In this post, I want to describe how I got it to push images build locally up to
googles artifact repository. It will include creating the artifac repository
using infrastructure as code</p>
<p>The project is in a <a href="https://icle.es/tags/monorepo">monorepo</a> that uses <a href="https://icle.es/tags/bazel">bazel</a>.</p>
<h2 id="the-executable-to-be-packaged">The executable to be packaged</h2>
```starlark
# //products/example/cmd/server/BUILD.bazel
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")

go_library(
    name = "server_lib",
    srcs = ["main.go"],
    visibility = ["//visibility:private"],
)

go_binary(
    name = "server",
    embed = [":server_lib"],
    visibility = ["//visibility:public"],
)
```
<h2 id="build-container-image">Build Container Image</h2>
<h3 id="add-rules_oci">add <code>rules_oci</code></h3>
<p><a href="https://github.com/bazel-contrib/rules_oci">rules_oci</a> is a good place to start
to integrate container support into your bazel configuration. It&rsquo;s also worth
<a href="https://github.com/GoogleContainerTools/distroless">reading up a bit on distroless</a>
if you are not aware of it.</p>
<p>Adding <code>rules_oci</code> into bazel <code>MODULES</code> is straightforward:</p>
```starlark
bazel_dep(name = "rules_oci", version = "2.2.6")
# For testing, we also recommend https://registry.bazel.build/modules/container_structure_test

oci = use_extension("@rules_oci//oci:extensions.bzl", "oci")

# Declare external images you need to pull, for example:
oci.pull(
    name = "distroless_base",
    # 'latest' is not reproducible, but it's convenient.
    # During the build we print a WARNING message that includes recommended 'digest' and 'platforms'
    # values which you can use here in place of 'tag' to pin for reproducibility.
    tag = "latest",
    image = "gcr.io/distroless/base",
    platforms = ["linux/amd64"],
)

# For each oci.pull call, repeat the "name" here to expose them as dependencies.
use_repo(oci, "distroless_base")
```
<p>If you use the <code>WORKSPACE</code>, or if you want the latest version, you
<a href="https://github.com/bazel-contrib/rules_oci/releases">can find details on their releases page</a>.</p>
<h3 id="tarbzl"><code>tar.bzl</code></h3>
<p><code>oci_rules</code> uses tar files to build the image. To build tar images, you will
want to use <a href="https://github.com/bazel-contrib/tar.bzl">tar.bzl</a>.</p>
<p>Add the following to you <code>MODULES</code></p>
```starlark
bazel_dep(name = "tar.bzl", version = "0.3.0")
```
<p>Latest version and instructions for <code>WORKSPACE</code>
<a href="https://github.com/bazel-contrib/tar.bzl/releases/tag/v0.3.0">can be found on their releases page</a></p>
<h3 id="buildbazel"><code>BUILD.bazel</code></h3>
<p>There are
<a href="https://github.com/bazel-contrib/rules_oci?tab=readme-ov-file#usage">language specific sample build files</a>
that you can start from.</p>
<p>Starting
<a href="https://github.com/aspect-build/bazel-examples/blob/main/oci_go_image/BUILD.bazel">from the example go <code>BUILD.bazel</code></a>,
and simplifying it, I have:</p>
```starlark
# //products/example/deploy/BUILD.bazel
load("@rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
load("@rules_oci//oci:defs.bzl", "oci_image", "oci_load", "oci_push")
load("@tar.bzl", "mutate", "tar")

# Put app go_binary into a tar layer.
tar(
    name = "app_layer",
    srcs = ["//products/muster/cmd/server:server"],
    out = "app_layer.tar",
    mutate = mutate(strip_prefix = package_name() + "/app_"),
)


oci_image(
    name = "image",
    # This is defined by an oci.pull() call in /MODULE.bazel
    base = "@distroless_base",
    entrypoint = ["/app"],
    # Link the resulting image back to the repository where the build is defined.
    labels = {
        "org.opencontainers.image.source": "https://github.com/aspect-build/bazel-examples",
    },
    tars = [":app_layer"],
)
```
<p>There is
<a href="https://github.com/bazel-contrib/rules_oci/blob/main/docs/go.md">more information at the go doc page</a>
including details of migrating from
<a href="https://github.com/bazelbuild/rules_docker"><code>rules_docker</code></a></p>
```bash
products/example/deploy $ bazel build ...
INFO: Analyzed 2 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets...
INFO: Elapsed time: 0.444s, Critical Path: 0.07s
INFO: 2 processes: 1 internal, 1 linux-sandbox.
INFO: Build completed successfully, 2 total actions
```
<p>Building of the images now completes</p>
<h2 id="push-image">Push Image</h2>
<p>Pushing the image can be pretty straightforward:</p>
<ul>
<li>Enable the container repository in <a href="https://icle.es/tags/google-cloud">Google Cloud</a></li>
<li>Configure it in the <code>BUILD.bazel</code> file</li>
<li><code>bazel run</code> to push</li>
</ul>
<p>I would like to do the whole thing through <a href="https://icle.es/tags/iac">IaC</a> so that it is</p>
<ul>
<li>Repeatable, and</li>
<li>more importantly documented</li>
</ul>
<h3 id="iac-tool-options">IaC Tool Options</h3>
<p><a href="https://developer.hashicorp.com/terraform">terraform</a> has no bazel support, and
is a questionable choice from an ethics perspective. <a href="https://icle.es/">opentofu</a> has</p>
<p><a href="https://github.com/yanndegat/rules_tf">rules_tf</a>. However, that
<a href="https://github.com/yanndegat/rules_tf/issues/5">does not support <code>apply</code></a></p>
<p><a href="https://cloud.google.com/infrastructure-manager/docs">Google Cloud Infrastucture Manager</a>
is vendor lock in.</p>
<p>That leaves us with <a href="https://www.pulumi.com/">pulumi</a> (If there is another
alternative, please let me know).</p>
<p>I like the stacks concept in pulumi, and while it doesn&rsquo;t have bazel
integration, what it does have is an
<a href="https://github.com/pulumi/automation-api-examples">automation api</a>. While not
he best documented, there is enough documentation out there to be able to piece
it together.</p>
<p>With this, we can build a runnable unit, and then run it too. I&rsquo;ve experimented
with tagging specific runnables and then running them through the CI. I won&rsquo;t
get that far in this post. My focus here is to get it working locally.</p>
<h3 id="enable-artifact-repository">Enable Artifact Repository</h3>
<p>In pulumi, you can enable the artifact repository with:</p>
```go

func enableArtifactRepository(ctx *pulumi.Context) error {
	// Set your GCP project and region
	projectID := "<projectId>"
	region := "europe-west1"
	repoName := "<repo-name>"

	// Create Artifact Registry repository
	repo, err := artifactregistry.NewRepository(ctx, repoName, &artifactregistry.RepositoryArgs{
		Format:       pulumi.String("DOCKER"),
		Location:     pulumi.String(region),
		RepositoryId: pulumi.String(repoName),
		Description:  pulumi.String("Repository for OCI container images"),
		Project:      pulumi.String(projectID),
	})
	if err != nil {
		return err
	}

	// Export the repository URL (used for pushes)
	ctx.Export("repositoryURL", pulumi.Sprintf("%s-docker.pkg.dev/%s/%s", region, projectID, repo.Name))

	return nil

}
```
<h3 id="authenticating-against-the-repo">Authenticating against the repo</h3>
<p>You need to authenticate against the repository so that the <code>oci_rule</code> can pick
it up</p>
```bash
gcloud auth configure-docker europe-west1-docker.pkg.dev
```
<h3 id="define-the-push-target">Define the push target</h3>
```starlark
oci_push(
    name = "push",
    image = ":image",
    remote_tags = [
        "latest",
        "1h",
    ],
    repository = "europe-west1-docker.pkg.dev/<projectId>/<repo-name>/<image-name>",
)
```
<h2 id="pushing">Pushing</h2>
<p>Once all the above is set up, you can then push the image with one of the
following:</p>
```bash
bazel run :push # if you in the directory
bazel run //<target/path>:push # fron anywhere in the repo
```
<h2 id="side-note">Side note</h2>
<p>Please do not take my heavy usage of google and its products to be a fan letter
or an endorsement. They <em>might</em> at best, be the lesser evil.</p>]]></content:encoded></item><item><title>Getting Docker Desktop Working with WSL2 on Windows</title><link>https://icle.es/2020/05/28/getting-docker-desktop-working-with-wsl2-on-windows/</link><pubDate>Thu, 28 May 2020 17:29:52 +0000</pubDate><guid>https://icle.es/2020/05/28/getting-docker-desktop-working-with-wsl2-on-windows/</guid><description>&lt;p>I ran into several issues while trying to get this to work. Here are the steps I
had to complete to get it working. Hopefully this will save some hair on your
head ;)&lt;/p>
&lt;p>The main step is to go into the settings in Docker Desktop -&amp;gt; Resources and
make sure that your distribution is enabled for docker.&lt;/p>
&lt;p>
 &lt;img src="https://icle.es/assets/2020/05/image.png" alt="enable your distro on docker">

&lt;/p>
&lt;ol>
&lt;li>Make sure that you have no docker packages installed on your WSL
distribution. Docker Desktop will deploy its own binaries, and any
pre-existing binaries will confuse it. This issue exhibited itself for me
with errors related to missing files around credentials.&lt;/li>
&lt;li>Remove any &lt;code>DOCKER_HOST &lt;/code>environment variables. Docker Desktop will sort it
out. Docker kept hanging for me until I fixed this.&lt;/li>
&lt;li>If you want to use docker as non-root user, add yourself to the
&lt;code>docker &lt;/code>group.&lt;/li>
&lt;/ol>
&lt;p>Errors / Issues I ran into:&lt;/p></description><content:encoded><![CDATA[<p>I ran into several issues while trying to get this to work. Here are the steps I
had to complete to get it working. Hopefully this will save some hair on your
head ;)</p>
<p>The main step is to go into the settings in Docker Desktop -&gt; Resources and
make sure that your distribution is enabled for docker.</p>
<p>
  <img src="/assets/2020/05/image.png" alt="enable your distro on docker">

</p>
<ol>
<li>Make sure that you have no docker packages installed on your WSL
distribution. Docker Desktop will deploy its own binaries, and any
pre-existing binaries will confuse it. This issue exhibited itself for me
with errors related to missing files around credentials.</li>
<li>Remove any <code>DOCKER_HOST </code>environment variables. Docker Desktop will sort it
out. Docker kept hanging for me until I fixed this.</li>
<li>If you want to use docker as non-root user, add yourself to the
<code>docker </code>group.</li>
</ol>
<p>Errors / Issues I ran into:</p>
<p><code>docker.credentials.errors.InitializationError: docker-credential-desktop.exe not installed or not available in PATH</code> -
Fixed by 1 above.</p>
<p><code>docker-compose</code> from WSL2 errors out - Again, fixed by 1</p>
<p>Unable to run <code>docker</code> as non-root user - fixed by 3.</p>
<p>Docker hangs when run as non-root user - fixed by 2.</p>
]]></content:encoded></item></channel></rss>