I’m working at Docker for 5 years now. And even before to join I was already thinking about ways to improve docker run. docker runx is my most recent attempt at it, and here is why.

A Use Case: docker/scout-cli

To understand the reasons behind docker runx, let’s first look at the current state of docker run. And to do that I’ll use the image docker/scout-cli as an example.

Why this image in particular?

Because my day work at Docker is about Docker Scout and in particular to build the scout CLI embedded in this image. So I prefer to use this one than someone else’s image. I even gave a talk about it at DockerCon 2023.

If you are running quite frequently containers on your machine, you probably have some habits. Mine are to always run containers with the following flags:

  • --rm to remove the container when it stops
  • -it to have an interactive terminal

That’s the basic. I mean, all time, except if I have a good reason not to. But it can be nice to not have to worry about that anymore.

So, let’s start with docker/scout-cli and see how that goes:

$ docker run -it --rm docker/scout-cli
Command line tool for Docker Scout

 Command line tool for Docker Scout

Usage
  docker-scout [command]

Available Commands
  attestation             Manage attestations on image indexes
  cache                   Manage Docker Scout cache and temporary files
  compare                 Compare two images and display differences (experimental)
  completion              Generate the autocompletion script for the specified shell
  config                  Manage Docker Scout configuration
  cves                    Display CVEs identified in a software artifact
  enroll                  Enroll an organization with Docker Scout
  environment             Manage environments (experimental)
  help                    Help about any command
  help                    Display information about the available commands
  integration             Commands to list, configure, and delete Docker Scout integrations
  policy                  Evaluate policies against an image and display the policy evaluation results (experimental)
  push                    Push an image or image index to Docker Scout
  quickview               Quick overview of an image
  recommendations         Display available base image updates and remediation recommendations
  repo                    Commands to list, enable, and disable Docker Scout on repositories
  version                 Show Docker Scout version information

Flags
  -h, --help   help for docker-scout

Use "docker-scout [command] --help" for more information about a command.

Learn More
  Read docker scout cli reference at https://docs.docker.com/engine/reference/commandline/scout/

Report Issues
  Raise bugs and feature requests at https://github.com/docker/scout-cli/issues

Send Feedback
  Send feedback with docker feedback

OK, it prints the help.

Now, let’s start a command. I’ll use the quickview command as an exemple, but it could be any other command.

The command I want to run in the end is docker scout quickview alpine. Easy one.

$ docker run --rm -it docker/scout-cli quickview alpine

That should be it.

Log in with your Docker ID or email address to use docker scout.

If you don't have a Docker ID, head over to https://hub.docker.com to
create one. You can log in with your password or a Personal Access Token (PAT)
by running docker login.
Using a limited-scope PAT grants better security and is required for organizations
using SSO. Learn more at https://docs.docker.com/go/access-tokens/

You can also log in using Docker Desktop.

Well, that’s not what I expected. Especially I’m already logged in on my computer. And as it’s the help of the docker scout command and not a specific help for the container, I’m not entirely sure what to do.

By looking at the image documentation on Docker Hub, this helps me:

Usage

To run the CLI you need to be authenticated with Docker Hub. Pass your credentials to the docker run command like follows:

$ docker run -it \
-e DOCKER_SCOUT_HUB_USER=<your Docker Hub user name> \
-e DOCKER_SCOUT_HUB_PASSWORD=<your Docker Hub PAT>  \
docker/scout-cli <sub command>

That’s ok, but it means I had to leave my current terminal, go to the doc page. And it could be nice if there was a way to have this information directly in the terminal. A more proactive way to help the user.

But ok, let’s do it. (of course you have to provide that to your terminal. Go to docker hub to generate a specific personal access token)

$ docker run --rm -it \
  -e DOCKER_SCOUT_HUB_USER \
  -e DOCKER_SCOUT_HUB_PASSWORD \
  docker/scout-cli quickview alpine

It kind of works.

    i Failed to connect to Docker Engine. Please run the container with '-u root -v /var/run/docker.sock:/var/run/docker.sock' to access local images.
    ✓ Pulled
    ✓ Image stored for indexing
    ✓ Indexed 17 packages

    i Base image was auto-detected. To get more accurate results, build images with max-mode provenance attestations.
      Review docs.docker.com ↗ for more information.

  Target   │  alpine:latest  │    0C     0H     0M     0L
    digest │  9cee2b382fe2   │

What's next:
    Include policy results in your quickview by supplying an organization → docker scout quickview alpine --org <organization>

But if you look at the first line, it’s not perfect. Maybe I wanted to use it against a local image and I have to re-run it again with more flags.

So from here, I ran the container 3 or 4 times, added each time some flags, and finally got a result. And next time I want to run it again I’ll have to not forget all that.

The docker runx Way

Now, let’s see how it goes with docker runx.

I’ll use the image eunomie/scout-cli (and you can use it too, it’s available on Docker Hub). This image is just a mirror of the official docker/scout-cli image with some extra data we’ll see later.

$ docker runx eunomie/scout-cli
┃ Select the action to run
┃ > help: Print Docker Scout CLI help
┃   self: Run quickview against the image itself (required env: DOCKER_SCOUT_HUB_USER, DOCKER_SCOUT_HUB_PASSWORD)
┃   qv: Run docker scout quickview command (required env: DOCKER_SCOUT_HUB_USER, DOCKER_SCOUT_HUB_PASSWORD)
┃   cves: Run docker scout cves command (required env: DOCKER_SCOUT_HUB_USER, DOCKER_SCOUT_HUB_PASSWORD)
┃   cves:pkgs: List vulnerable packages only and ignore the base image (required env: DOCKER_SCOUT_HUB_USER, DOCKER_SCOUT_HUB_PASSWORD)

That’s quite different. I have a list of actions I can run. And I can select one of them. On each of them, I have a description of what it does and what environment variables are required.

If I’m trying to pick one of the command without to provide the required environment variable, it will block me.

environment variable "DOCKER_SCOUT_HUB_USER" is required

I can re-run this command with the --help flag to see the help of the image (and not the help of the docker scout command).

$ docker runx eunomie/scout-cli --help
   Docker Scout

  This image bundles the Docker Scout CLI.

  Read more about the CLI at https://docs.docker.com/engine/reference/commandline/scout/ https://docs.docker.com/engine/reference/commandline/scout/.

  ## Usage

  To run the CLI you need to be authenticated with Docker Hub. To pass your credentials to Docker Scout CLI, pass the following environment variables:

  •  DOCKER_SCOUT_HUB_USER : Your Docker Hub user name.
  •  DOCKER_SCOUT_HUB_PASSWORD : Your Docker Hub Personal Access Token (PAT).

  You can then run the CLI with the following command:

    $ docker run -it \
      -e DOCKER_SCOUT_HUB_USER=<your Docker Hub user name> \
      -e DOCKER_SCOUT_HUB_PASSWORD=<your Docker Hub PAT>  \
      docker/scout-cli <sub command>

  Run the  docker/scout-cli  image with the  --help  flag (or with no sub command) to see the available sub commands.

    $ docker run -it docker/scout-cli --help

  If you want to access local images, you need to mount the Docker socket:

    $ docker run -it \
      -e DOCKER_SCOUT_HUB_USER \
      -e DOCKER_SCOUT_HUB_PASSWORD \
      -u root \
      -v /var/run/docker.sock:/var/run/docker.sock \
      docker/scout-cli <sub command>

  ## Customization

  If you want to always run the CLI for your organization namespace, create a  .docker/runx.yaml  file in your current folder with the following content:

    images:
      runx/scout-cli:
        all-actions:
          opts:
            org: <your organization>

  --------

   Available actions

  •  help : Print Docker Scout CLI help
  •  self : Run quickview against the image itself
  •  qv : Run docker scout quickview command
  •  cves : Run docker scout cves command
  •  cves:pkgs : List vulnerable packages only and ignore the base image

  │ Use  docker runx IMAGE ACTION --help  to get more details about an action

This documentation is embedded inside the image. I don’t have to leave the terminal. It helps me to run the image, and show me the different available actions.

Let’s export the two required environment variables and try the qv action.

$ docker runx eunomie/scout-cli

It’s also possible to directly run the command using docker runx eunomie/scout-cli qv

┃ Please enter the image reference
┃ The image reference
┃ >

The tool will asked me for the image reference, I want to run it for alpine.


  │ Running the following command:

    docker run  \
    -e DOCKER_SCOUT_HUB_USER \
    -e DOCKER_SCOUT_HUB_PASSWORD \
    -u root \
    -v /var/run/docker.sock:/var/run/docker.sock \
    --rm -it \
    eunomie/scout-cli quickview  alpine


  --------

  │ Some flags require your attention:

  •  volume


┃ Continue?
┃
┃   Yes     No

Then it will show me the real docker run command that will be used. That way I can see if everything is correct, but also learn from it. What are the flags used for instance. It’s easy then to copy/paste the command to tweak it if needed.

But as it’s using a volume, I have to confirm that I want to continue. This ensures you are not sharing unwanted data to the container. Some other flags will also require a confirmation, like --privileged for instance.

And if you continue, it will run the command as expected.

    ✓ Image stored for indexing
    ✓ Indexed 17 packages

    i Base image was auto-detected. To get more accurate results, build images with max-mode provenance attestations.
      Review docs.docker.com ↗ for more information.

  Target   │  alpine:latest  │    0C     0H     0M     0L
    digest │  beefdbd8a1da   │

What's next:
    Include policy results in your quickview by supplying an organization → docker scout quickview alpine --org <organization>

And that’s it. From there you can run the exposed commands easily. You can learn from there, but you don’t have to remember all the specific flags.

And it’s not just about the container, it’s also about the software the container will run. For instance, if you try to run the cves:pkgs command. That’s not a docker scout command, that’s more a set of command and flags.

$ docker runx eunomie/scout-cli cves:pkgs

  │ Running the following command:

    docker run  \
    -e DOCKER_SCOUT_HUB_USER \
    -e DOCKER_SCOUT_HUB_PASSWORD \
    -u root \
    -v /var/run/docker.sock:/var/run/docker.sock \
    --rm -it \
    eunomie/scout-cli cves \
    --format only-packages --only-vuln-packages --ignore-base \
     alpine

# ...

That way, again, it helps to get started on both the container and the software inside the container sides. It’s easier for repetitive tasks, and especially for new users.


On next post, I'll go deeper in the configuration possibilities, but also how docker runx images are made and how they can be created.

If you want to play with it, here is a few links to get started:

And if you have any question or feedback, feel free to reach out to me using the links below.