npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

docker-hash-build

v4.0.0

Published

A CLI that optimises Docker builds by allowing you to "check" if something needs to be built before triggering the build.

Downloads

76

Readme

docker-hash-build

This CLI can be used to reduce the number of times you "build" something unnecessarily. Even with cache in Docker, there is still a build time and this would reduce that time by checking if anything has changed before triggering the docker build command.

The docker-hash-build CLI stores a calculated hash on your Docker registry to ensure that you don't rebuild images that are already there. You're hash your whole repo, a few directories, and a few files to control when a rebuild is needed.

I use regclient to copy tags to quickly "retag" things that were built so you don't need to pull images down and push them back under the new tag. Thanks to the contributors or regclient for this incredible tool!

Part of the reason I built this was to ensure that I could reduce the build time, while catering for amd64 and arm64 builds. So you'll see that you can select the platform(s) you would like to build your images for, and docker buildx is used to create the images. A previous tool I created https://github.com/entrostat/entro-ci is able to perform a similar function but is written using basic docker functionality and does not cater for arm64 builds.

oclif GitHub license

Requirements

In order to use this CLI, you must have:

  • docker installed and accessible via the command line (and your user)
  • docker buildx support
  • (optional) regclient installed and accessible via the command line (and your user). If this is not installed, the docker-hash-build cli will curl for the binary file and install it for you. This will only work on an amd64 machine. If you have a different machine, installed regcli beforehand!

Usage

$ npm install -g docker-hash-build
$ docker-hash-build COMMAND
running command...
$ docker-hash-build (--version)
docker-hash-build/4.0.0 linux-x64 node-v16.20.1
$ docker-hash-build --help [COMMAND]
USAGE
  $ docker-hash-build COMMAND
...

I recommend using npx for convenience:

$ npx docker-hash-build build --help

Commands

docker-hash-build build DIRECTORY

Build a Docker image if the hash does not exist on the Docker registry.

USAGE
  $ docker-hash-build build DIRECTORY -i <value> [-f <value>] [-r <value>] [-t <value>] [-p <value>] [-w
    <value>] [-W <value>] [-b <value>] [-u <value>] [-P <value>] [-l] [-P
    linux/amd64|linux/arm64|linux/arm/v7|linux/arm/v6] [-x <value>]

ARGUMENTS
  DIRECTORY  The directory that represents the "context" for your docker build

FLAGS
  -P, --docker-password=<value>                The password for logging into the docker repository (mainly for if you
                                               are running this build process inside a container and have not logged
                                               docker in yet)
  -P, --platforms=<option>...                  [default: linux/amd64] The platforms that should be built for, e.g.
                                               "linux/amd64,linux/arm64"
                                               <options: linux/amd64|linux/arm64|linux/arm/v7|linux/arm/v6>
  -W, --watch-file=<value>...                  Files that should be watched to trigger the build. Note, if you set this
                                               then it IGNORES the build directory so you'd have to add that here as
                                               well.
  -b, --docker-build-flags=<value>...          Any additional build flags that you would like to plug directly into the
                                               Docker build command
  -f, --dockerfile-path=<value>                The path to the Dockerfile, if not specified, it's assumed that the file
                                               is in the context directory
  -i, --image-name=<value>                     (required) The name of the image that should be built
  -l, --latest                                 Whether to push the latest tag to the registry
  -p, --package=<value>                        [default: ./package.json] The path to the package.json that holds the
                                               version of the build, the default is the package.json in the directory
                                               the CLI is run from.
  -r, --registry=<value>                       The registry that should be used (by default Docker Hub is used)
  -t, --tag=<value>...                         The tag version that should be pushed to the registry so that it can be
                                               used in automated deployments. E.g. 'stable' or 'testing'
  -u, --docker-username=<value>                The username for logging into the docker repository (mainly for if you
                                               are running this build process inside a container and have not logged
                                               docker in yet)
  -w, --watch-directory=<value>...             Directories that should be watched to trigger the build. Note, if you set
                                               this then it IGNORES the build directory so you'd have to add that here
                                               as well.
  -x, --buildx-additional-build-flags=<value>  ADVANCED: Any additional build flags that you would like to plug directly
                                               into the Docker buildx build command

DESCRIPTION
  Build a Docker image if the hash does not exist on the Docker registry.

EXAMPLES
  $ docker-hash-build build . --image-name=kerren/docker-hash-build --platforms=linux/amd64 --platforms=linux/arm64

  $ docker-hash-build build ./path/to/repo --image-name=kerren/docker-hash-build

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --dockerfile-path=./Dockerfile.stable

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --tag=staging

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --tag=stable --latest

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --watch-file=./yarn.lock

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --watch-directory=./src

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --watch-directory=./src --watch-file=./yarn.lock

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --docker-username=username --docker-password=password --registry=registry.example.com

  $ docker-hash-build build . --image-name=kerren/docker-hash-build --buildx-additional-build-flags="--cache-to type=gha,mode=max,scope=$GITHUB_REF_NAME-image-name --cache-from type=gha,scope=$GITHUB_REF_NAME-image-name"

See code: dist/commands/build.ts

docker-hash-build help [COMMANDS]

Display help for docker-hash-build.

USAGE
  $ docker-hash-build help [COMMANDS] [-n]

ARGUMENTS
  COMMANDS  Command to show help for.

FLAGS
  -n, --nested-commands  Include all nested commands in the output.

DESCRIPTION
  Display help for docker-hash-build.

See code: @oclif/plugin-help

Detailed Explanation

I've tried to make this cli as functional as possible. But that does mean it may come across as a bit complicated. So I thought I'd explain a few of the concepts in detail here so avoid confusion.

Hashing

Hashing is run across the files and directories you specify. This is done using the sha256 algorithm. It recursively runs over files and combines the hashes for each one and finally hashes the combination of hashes from all directories, files, etc.

By default, the directory that you're triggering the build from is hashed. If you specify a file/folder or a combination to watch, it will no longer hash the build directory and will only look at the values you specified. This is useful if you have base docker images that you only want to rebuild when a .lock file (for example) changes.

The hash that gets generated is stored on the Docker registry as an image tag. This means that if you run the build again, it will check the hash against the registry and if it's the same, it will not rebuild the image. This is useful for CI/CD pipelines where you don't want to rebuild the image if nothing has changed.

Tagging

Tags are used to modify the tag attached to an image. If you use the --latest flag, it will tag your image with the latest tag. So, for instance, this image would be tagged as kerren/docker-hash-build:latest whenever it was built if I used that flag.

If you leave the --tag flag unset, it will tag the image with the latest version in your package.json which is assumed to be in the directory you're running the cli from (you can change this with the --package flag). So, for instance, if I've just run a release and the version in the package.json is 1.3.3, it will tag the image as kerren/docker-hash-build:v1.3.3.

The more exciting part is when you specify a tag(s). For instance, let's say you added two --tag flags, staging and beta. If the version in the package.json is 1.3.3, it will create the following image tags on the registry, kerren/docker-hash-build:staging-v1.3.3 and kerren/docker-hash-build:beta-v1.3.3. This is great for testing and setting up different environments. It means that you can use the same registry (ie. share the build hashes) and different tags per environment.

Docker Credentials

I recommend logging into your registry beforehand since this cli just calls the docker cli through terminal. However, if you would like to include the login credentials in the cli call (for example in CI/CD pipelines), you can specify the registry, username, and password.

Platforms

By default, images are built for amd64, but you are able to specify the platform that you would like to build for. Currently, I've added the following options: linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6. If you need any others, please open an issue or PR the change into the repo.

Custom buildx flags

I've added the ability for you to plug in buildx build flags directly using the --buildx-additional-build-flags flag. This allows you to set up things like caching. For instance, for Github, here's a great article on caching Github Actions builds using buildx.

An example of how this may look would be:

--buildx-additional-build-flags="--cache-to type=gha,mode=max,scope=${GITHUB_REF_NAME}-docker-hash-build --cache-from type=gha,scope=${GITHUB_REF_NAME}-docker-hash-build"               

This is quite complicated but it does allow you to tweak the build command a bit and potentially optimise your build process further!

Getting Started (Contributing)

To develop on the project, clone it and run:

make init

If you have zsh you can use autoenv to automatically use the node environment set up for you. Otherwise, you'll have to run:

source .nodeenv/bin/activate