How to use rules_oci to run an image local via Docker?

1.6k views Asked by At

I want to use rules_oci to build a (docker) image that I can run locally as a container. Here is my try:

WORKSPACE.bazel:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

#-------------------------------------------------------
# rules_oci
#-------------------------------------------------------

http_archive(
    name = "rules_oci",
    sha256 = "176e601d21d1151efd88b6b027a24e782493c5d623d8c6211c7767f306d655c8",
    strip_prefix = "rules_oci-1.2.0",
    url = "https://github.com/bazel-contrib/rules_oci/releases/download/v1.2.0/rules_oci-v1.2.0.tar.gz",
)

load("@rules_oci//oci:dependencies.bzl", "rules_oci_dependencies")

rules_oci_dependencies()

load("@rules_oci//oci:repositories.bzl", "LATEST_CRANE_VERSION", "LATEST_ZOT_VERSION", "oci_register_toolchains")

oci_register_toolchains(
    name = "oci",
    crane_version = LATEST_CRANE_VERSION,
)

load("@rules_oci//oci:pull.bzl", "oci_pull")

oci_pull(
    name = "ubuntu",
    digest = "sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428a6d21",
    image = "ubuntu",
    platforms = [
        "linux/arm64/v8",
        "linux/amd64",
    ],
)

#-------------------------------------------------------
# rules_pkg
#-------------------------------------------------------

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "rules_pkg",
    sha256 = "8f9ee2dc10c1ae514ee599a8b42ed99fa262b757058f65ad3c384289ff70c4b8",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.9.1/rules_pkg-0.9.1.tar.gz",
        "https://github.com/bazelbuild/rules_pkg/releases/download/0.9.1/rules_pkg-0.9.1.tar.gz",
    ],
)

load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies")

rules_pkg_dependencies()

BUILD.bazel:

load("@rules_oci//oci:defs.bzl", "oci_image",  "oci_tarball")
load("@rules_pkg//:pkg.bzl", "pkg_tar")

pkg_tar(
    name = "app",
    srcs = ["test.sh"],
)

oci_image(
    name = "image",
    base = "@ubuntu",
    cmd = ["test.sh"],
    tars = ["app.tar"],
)

oci_tarball(
    name = "tarball",
    image = ":image",
    repo_tags = ["vertexwahn/my_example:v0.0.1"],
)

test.sh:

echo "Hello World!"

.bazelversion:

6.3.2

If run:

# List all images
docker image ls
# Create an image
bazel run //:tarball
# Run docker container and delete it on quit
sudo docker run vertexwahn/my_example:v0.0.1

I get the following error:

docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "test.sh": executable file not found in $PATH: unknown.

Any ideas on how to solve this issue? I can also live with a bzlmod solution.

The code can also be found here.

2

There are 2 answers

1
G. Y. On BEST ANSWER

The answer provided above was mildly incorrect. Here is a full correction for BUILD.bazel:

load("@rules_oci//oci:defs.bzl", "oci_image", "oci_push", "oci_tarball")
load("@rules_pkg//:pkg.bzl", "pkg_tar")

pkg_tar(
    name = "app",
    srcs = ["test.sh"],
    mode = "0755",
    package_dir = "/usr/bin"
)

oci_image(
    name = "image",
    base = "@ubuntu",
    cmd = ["test.sh"],
    tars = [":app"],
)

oci_tarball(
    name = "tarball",
    image = ":image",
    repo_tags = ["vertexwahn/my_example:v0.0.1"],
)

oci_push(
    name = "push",
    image = ":image",
    remote_tags = ["v0.0.1"],
    repository = "vertexwahn/my_example",
)

And, for test.sh:

#!/usr/bin/sh

echo "Hello World!"

The previous answer struggled to get the execution working properly (path issue and stuff).

Note: you can use docker save to get the image in some kind of archive format and typically use mc (midnight commander) to navigate within the archive and the archive in the archive. You'll see that there is no /bin folder but only /usr/bin. Hence the fix. A shebang can't hurt, too...

3
VonC On

cmd = ["test.sh"], means you are relying on the $PATH for that test.sh to be executed.
And... ""test.sh": executable file not found in $PATH".

You could try and place test.sh into a directory that is already in the container's $PATH, or explicitly provide a path when running the command.

If we assume the /usr/bin folder is in the $PATH, update your BUILD.bazel pkg_tar with:

pkg_tar(
    name = "app",
    srcs = ["test.sh"],
    mode = "0755",  # Make sure it is executable
    package_dir = "/usr/bin",  # That will place test.sh into a '/usr/bin' directory in the tarball
)

oci_image(
    name = "image",
    base = "@ubuntu",
    cmd = ["/usr/bin/test.sh"],  # Adjust the cmd to use the script from the '/usr/bin' directory
    tars = [":app"],  # Correcting this to use the label of the pkg_tar rule
)

And, from the comments, adds a shebang line to test.sh:

#!/usr/bin/shshebang

echo "Hello World!"