Skip to content

Latest commit

 

History

History
647 lines (404 loc) · 18.6 KB

File metadata and controls

647 lines (404 loc) · 18.6 KB

Examples

List of examples:

Category Example title
Registry Copying images and charts between registries
Registry Copying images and charts from a file to a registry
Registry Checking available repositories on a docker private registry
Registry List all private registry repositories and corresponding tags
Docker Accessing the Docker daemon
Docker Using the host docker authentication
Kubernetes Accessing Kubernetes container runtime
Kubernetes Checking the images 'cached' on the current Kubernetes node
Kubernetes Loop the cpu, memory and storage metrics of each container on the current Kubernetes node
Images Checking images content
Images Checkout the files per layer on an existing image
Images Generate a BOM (Bill Of Materials) for a provided image
Images Retrieve a specific file from an image
Images Comparing file contents between two image tags
Images Squashing image layers to reduce size and improve performance
Images Add/Change files to specific layers on an image

To search for a specific example type '/Checking images content' and use the arrow keys to navigate

📸 Copying images and charts between registries

  1. Execute:
# With just docker
docker run --name imgutils --rm -ti nmaguiar/imgutils sudo /bin/bash

# With just kubectl
kubectl run imgutils --rm -ti --image=nmaguiar/imgutils -- sudo /bin/bash
  1. To copy from registry A to registry B, start by login into A and B:
skopeo login a.registry -u userA --password-stdin
[enter password for user A]
[hit Ctrl-D]

skopeo login b.registry -u userB --password-stdin
[enter password for user B]
[hit Ctrl-D]
  1. Copy the image or helm chart between registry A and registry B:
skopeo copy --all docker://a.registry/some/image:1.2.3 docker://b.registry/some/image:1.2.3

skopeo copy --all docker://a.registry/some/chart:1.2.3 docker://b.registry/some/chart:1.2.3
  1. Exit image:
exit

📸 Copying images and charts from a file to a registry

  1. Execute:
# With just docker
docker run --name imgutils --rm -ti nmaguiar/imgutils sudo /bin/bash

# With just kubectl 
kubectl run imgutils --rm -ti --image=nmaguiar/imgutils -- sudo /bin/bash
  1. Copy the images and charts to the running image
# With just docker
docker cp myImageOrChart.tgz imgutils:/tmp/myImageOrChart.tgz

# With just kubectl
kubectl cp myImageOrChart.tgz imgutils:/tmp/myImageOrChart.tgz
  1. Login into the target registry
skopeo login b.registry -u userB --password-stdin
[enter password for user B]
[hit Ctrl-D]

helm registry login b.registry -u userB --password-stdin
[enter password for user B]
[hit Ctrl-D]
  1. Copy the image to the target registry
skopeo copy --all docker-archive:/tmp/myImage.tgz docker://b.registry/some/image-or-chart:1.2.3

or copy the chart to the target registry

helm push /tmp/myChart.tgz oci://some/chart
  1. Exit image:
exit

🐳 Accessing the Docker daemon

With docker you can execute directly:

docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils sudo /bin/bash

Then you can execute commands like:

$ docker images
[...]
$ docker ps
[...]
$ docker rmi some/image
[...]

To exit just execute:

exit

⚙️ Accessing Kubernetes container runtime

AWS EKS with crictl

To use crictl on a specific node (change from "server-0" to the specific node you want):

NODENAME=ec2-server-0 NAME=imgutils HPATH=/run/containerd/containerd.sock  /bin/sh -c 'kubectl run -n kube-system $NAME --rm -ti --image=nmaguiar/imgutils  --overrides="{\"apiVersion\":\"v1\",\"spec\":{\"nodeName\":\"$NODENAME\",\"containers\":[{\"name\":\"$NAME\",\"image\":\"nmaguiar/imgutils\",\"stdin\":true,\"stdinOnce\":true,\"tty\":true,\"args\":[\"sudo\",\"-E\",\"/bin/bash\"],\"env\":[{\"name\":\"CONTAINER_RUNTIME_ENDPOINT\",\"value\":\"unix:///run/containerd/containerd.sock\"}],\"volumeMounts\":[{\"name\":\"cri\",\"mountPath\":\"/run/containerd/containerd.sock\"}]}],\"volumes\":[{\"name\":\"cri\",\"hostPath\":{\"path\":\"$HPATH\"}}]}}" -- sudo -E /bin/bash'

Then you can execute commands like:

$ crictl images
[...]
$ crictl ps
[...]
$ crictl rmi docker.io/some/image:latest
[...]

To exit just execute:

exit

K3S with crictl

To use crictl on a specific node (change from "k3s-server-0" to the specific node you want):

NODENAME=k3s-server-0 NAME=imgutils HPATH=/run/k3s/containerd/containerd.sock  /bin/sh -c 'kubectl run -n kube-system $NAME --rm -ti --image=nmaguiar/imgutils  --overrides="{\"apiVersion\":\"v1\",\"spec\":{\"nodeName\":\"$NODENAME\",\"containers\":[{\"name\":\"$NAME\",\"image\":\"nmaguiar/imgutils\",\"stdin\":true,\"stdinOnce\":true,\"tty\":true,\"args\":[\"sudo\",\"-E\",\"/bin/bash\"],\"env\":[{\"name\":\"CONTAINER_RUNTIME_ENDPOINT\",\"value\":\"unix:///run/containerd/containerd.sock\"}],\"volumeMounts\":[{\"name\":\"cri\",\"mountPath\":\"/run/containerd/containerd.sock\"}]}],\"volumes\":[{\"name\":\"cri\",\"hostPath\":{\"path\":\"$HPATH\"}}]}}" -- sudo -E /bin/bash'

Then you can execute commands like:

$ crictl images
[...]
$ crictl ps
[...]
$ crictl rmi docker.io/some/image:latest
[...]

To exit just execute:

exit

OpenShift with crictl

To use crictl on a specific OpenShift node (change from "server-0" to the specific node you want):

NODENAME=server-0 NAME=imgutils HPATH=/var/run/crio/crio.sock  /bin/sh -c './kubectl run -n kube-system $NAME --rm -ti --image=nmaguiar/imgutils  --overrides="{\"apiVersion\":\"v1\",\"spec\":{\"nodeName\":\"$NODENAME\",\"containers\":[{\"name\":\"$NAME\",\"image\":\"nmaguiar/imgutils\",\"securityContext\":{\"privileged\":true},\"stdin\":true,\"stdinOnce\":true,\"tty\":true,\"args\":[\"sudo\",\"-E\",\"/bin/bash\"],\"env\":[{\"name\":\"CONTAINER_RUNTIME_ENDPOINT\",\"value\":\"unix:///run/crio/crio.sock\"}],\"volumeMounts\":[{\"name\":\"cri\",\"mountPath\":\"/run/crio/crio.sock\"}]}],\"volumes\":[{\"name\":\"cri\",\"hostPath\":{\"path\":\"$HPATH\"}}]}}" -- sudo -E /bin/bash'

Then you can execute commands like:

$ crictl images
[...]
$ crictl ps
[...]
$ crictl rmi docker.io/some/image:latest
[...]

To exit just execute:

exit

🔎 Checking images content

To check images use the following commands within the imgutils/nmaguiar:

$ dive docker.io/some/image:latest
[...]
$ docker image save some/image:latest > image.tar
[...]
$ imgInfo.yaml image=image.tar __format=json > image.json

# Check the manifest of the image
$ oafp image.json path=info out=ctree
# Check how many entries are there of each layer
$ oafp image.json path=layers out=ctable sql='select "layer", "layerFile" id, count(*) "numberOfEntries" group by "layer"'
# List the files on layer 1 (layer numbering starts in 0)
$ oafp image.json path="layers[?layer==\`1\`].filepath" out=yaml
# List the file entry differences between layer 2 and layer 3
$ oafp image.json path="layers | { a: [?layer==\`2\`].filepath, b: [?layer==\`3\`].filepath }" diff="(a:a,b:b)" color=true
# List the file entry differences between layer 2 and layer 3 including file size
$ oafp image.json path="layers | { a: [?layer==\`3\`].{filepath:filepath,size:size}, b: [?layer==\`4\`].{filepath:filepath,size:size} }" diff="(a:a,b:b)" color=true

🔎 Checkout the files per layer on an existing image

$ skopeo copy docker://library/nginx:latest docker-archive:image.tar
$ imgExpand.yaml image=image.tar output=output json=image.json
# Check the output for the entrypoint and other information about the image
$ cd output
$ mc
# then use the midnight-commander UI to check the contents on each layer

✏️ Changing files on an existing image

To create a new image with changes to files on an existing image:

$ skopeo copy docker-daemon:my-image:latest docker-archive:my-image.tar
# Expand the image with the corresponding layers (if you don't choose it you will save an image with one layer only after changing)
$ imgExpand.yaml image=my-image.tar output=my-image json=my-image.json usetar=true layers=true
# Make the changes you need on the files of the folder my-image and then get back to the original folder
# ...
$ imgCollapse.yaml image=my-image.tar input=my-image json=my-image.json usetar=true
# Copy the new changed image
$ skopeo copy docker-archive:my-image.tar docker-daemon:my-image:v2
# Test your changed image
$ docker run --rm -ti my-image:v2

🐳 Using the host docker authentication

To start imgutils/nmaguiar with the local host docker authentication:

docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock -v $HOME:/work nmaguiar/imgutils /bin/sh -c "mkdir /home/openaf/.docker && sudo cp /work/.docker/config.json /home/openaf/.docker/. && sudo chmod a+r /home/openaf/.docker/*&& /bin/bash"

🐳 Checking available repositories on a docker private registry

Not all private container registries allow the listing of their repositories. But if they do you can try:

oafp libs=dockerregistry in=registryrepos inregistryurl=http://registry:5000 data="()"

Check for more options with 'oafp libs=dockerregistry help=dockerregistry'


⚙️ Checking the images 'cached' on the current Kubernetes node

If you are currently running on a Kubernetes node (following the deploy instructions in 'usage-help') you can list the 'cached' images on it by executing:

crictl images | oafptab sql="select * order by IMAGE,TAG"

You can additionally force pulling an image:

crictl pull my-registry/my/image:1.2.3

Or even delete an unused image:

crictl rmi 6b963af3240f2

Use the IMAGE ID field value


⚙️ Loop the cpu, memory and storage metrics of each container on the current Kubernetes node

If you are currently running on a Kubernetes node (following the deploy instructions in 'usage-help') you can obtain each containers' metrics:

oafp cmd="crictl stats -o json" path="stats[].{ns:attributes.labels.\"io.kubernetes.pod.namespace\",pod:attributes.labels.\"io.kubernetes.pod.name\",name:attributes.metadata.name,cpuUsageCores:cpu.usageNanoCores.value,memWorkSet:memory.workingSetBytes.value,memAvail:memory.availableBytes.value,memUsage:memory.usageBytes.value,memRss:memory.rssBytes.value,memPageFault:memory.pageFaults.value,memMajorPageFaults:memory.majorPageFaults.value,ephUsed:writableLayer.usedBytes.value,ephInodes:writableLayer.inodesUsed.value}" from="sort(ns,pod,name)" out=ctable loop=2 loopcls=true

🐳 List all private registry repositories and corresponding tags

Given a private container registry you can list a table of all repositories and corresponding tags to visualize and/or import it, as csv, to other tools.

As a table

oafp libs=dockerregistry in=registryrepos data={} inregistrytags=true out=ctable inregistryurl=http://my.registry:5000

As a CSV

oafp libs=dockerregistry in=registryrepos data={} inregistrytags=true out=csv inregistryurl=http://my.registry:5000

You can check more options by executing 'oafp libs=dockerregistry help=dockerregistry'


🐳 Generate a BOM (Bill Of Materials) for a provided image

You can use the syft tool to generate a CycloneDX JSON BOM (Bill Of Materials) file:

syft scan nmaguiar/imgutils -o cyclonedx-json

🐳 Retrieve a specific file from an image

From a registry image

docker run --rm -ti --pull always -e REGAUTH="user,pass,my.registry" -v $(pwd):/output nmaguiar/imgutils catFileInImage.sh ubuntu:latest /etc/lsb-release /output/lsb-release
cat lsb-release

From the local docker daemon

docker run --rm -ti --pull always -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils oafp cmd="catFileInImage.sh docker-daemon:ubuntu:latest /etc/lsb-release" in=ini out=ctree

From a local container image file

# docker run --rm -ti --pull always -v $(pwd):/output nmaguiar/imgutils skopeo copy docker://ubuntu:late
st docker-archive:/output/image.tar
docker run --rm -ti --pull always -v $(pwd):/input nmaguiar/imgutils oafp cmd="catFileInImage.sh /input/image.tar /etc/lsb-release" in=ini out=map

+ Add/Change files to specific layers on an image

For debugging proposes you quickly add or change files, on specific layers, without the need to rebuild an image.

Steps:

  1. Obtain the source docker image archive and expand the corresponding layers to a folder:
expandLayersInImage.sh alpine:latest image
  1. In the layer(s) you want change or add the necessary files:
echo world > image/123*/root/hello

Check the layers of your source image on the 'image' folder to determine where to add or change files

  1. Collapse the layers back into a new docker image archive:
imgCollapse.yaml image=new-image.tar input=image json=image.json
  1. Test the new image:
docker copy docker-archive:new-image.tar docker-daemon:test:latest
docker run --rm -ti test

$ cat /root/hello
world

🐳 Comparing file contents between two image tags

If you have two image with different tabs for which you would like to understand which files are different, at the file content level, you can use compareImages.sh:

From registry images

docker run --rm -ti --pull always -e REGAUTH="user,pass,my.registry" -v $(pwd):/output nmaguiar/imgutils /bin/sh -c "compareImages.sh ubuntu:latest ubuntu:rolling && cp *.csv /output"

The first and the second arguments are the images to compare

As a result you will obtain:

File Description
A.csv A list of files with full path, size, date, permissions, user, group and md5 checksum from the first provided image on the arguments
B.csv A list of files with full path, size, date, permissions, user, group and md5 checksum from the second provided image on the arguments
AB-diff.csv An equivalent list to A.csv and B.csv but filtering for records that are different. It adds a first column with 'a' or 'b' to indicate in which list the records differ. This let's you know if files were added, removed or changed.

Besides the two images to compare if you provide a third argument, like 'out=ctable', it will be used as an oafp option to show the AB-diff.csv result at the end of processing.

From the local docker daemon

docker run --rm -ti --pull always -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd):/output nmaguiar/imgutils /bin/sh -c "compareImages.sh docker-daemon:ubuntu:latest ubuntu:rolling && cp *.csv /output"

The options and output files are equal to the 'From registry images'

From local container images

# docker run --rm -ti --pull always -v $(pwd):/output nmaguiar/imgutils skopeo copy docker://ubuntu:late
st docker-archive:/output/image.tar
docker run --rm -ti --pull always -v $(pwd):/input nmaguiar/imgutils /bin/sh -c "compareImages.sh /input/imageA.tar /input/imageB.tar && cp *.csv /input"

The options and output files are equal to the 'From registry images'


🔨 Squashing image layers to reduce size and improve performance

Squashing layers can reduce image size and improve performance by combining multiple layers into one. This is particularly useful after running multiple RUN commands during development.

From the Docker daemon

# Start imgutils with docker socket access
docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils /bin/bash

# Squash all layers of an image
squash.sh -t myapp:squashed docker-daemon:myapp:latest

# Verify the squashed image
docker images myapp

Squashing from a specific layer

# Start imgutils
docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils /bin/bash

# First, inspect the image to find layer information
dive docker-daemon:myapp:latest
# or use docker history
docker history myapp:latest

# Squash from layer 5 onwards (keeping first 5 layers separate)
squash.sh -f 5 -t myapp:squashed docker-daemon:myapp:latest

Squashing from a registry image

# Start imgutils
docker run --rm -ti nmaguiar/imgutils /bin/bash

# Squash all layers from a registry image
squash.sh -t myapp:squashed myapp:latest

# The squashed image can be pushed back to the registry
docker push myapp:squashed

Squashing and saving to a file

# Start imgutils with volume mount
docker run --rm -ti -v $(pwd):/output -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils /bin/bash

# Squash and save to a tar file
squash.sh -o /output/squashed.tar -t myapp:squashed docker-daemon:myapp:latest

# Exit and load the squashed image on another system
exit
docker load -i squashed.tar

Advanced options

# Squash with custom commit message
squash.sh -m "Optimized for production" -t myapp:prod docker-daemon:myapp:dev

# Squash from a specific layer ID with verbose output
squash.sh -f sha256:abc123def456... -v -t myapp:squashed docker-daemon:myapp:latest

# Use custom temporary directory
squash.sh --tmp-dir /mnt/fast-storage -t myapp:squashed docker-daemon:myapp:latest

Comparing before and after

# Check original image size and layers
docker images myapp:latest
docker history myapp:latest

# Squash the image
squash.sh -t myapp:squashed docker-daemon:myapp:latest

# Compare sizes
docker images | grep myapp
# Compare layer count
docker history myapp:squashed

Single docker run command line

Run squash.sh directly without entering an interactive shell:

# Squash all layers of a local docker image (result loaded back into docker daemon)
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils squash.sh -t myapp:squashed docker-daemon:myapp:latest

# Squash a registry image and save the result to a local tar file
docker run --rm -v $(pwd):/output nmaguiar/imgutils squash.sh -o /output/squashed.tar myapp:latest

# Squash a local docker image and save the result to a local tar file
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd):/output nmaguiar/imgutils squash.sh -o /output/squashed.tar docker-daemon:myapp:latest

# Squash from layer 3 onwards and load back into the docker daemon
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils squash.sh -f 3 -t myapp:squashed docker-daemon:myapp:latest

# Squash with verbose output
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nmaguiar/imgutils squash.sh -v -t myapp:squashed docker-daemon:myapp:latest

# Squash a registry image using a custom temporary directory
docker run --rm -v $(pwd):/work nmaguiar/imgutils squash.sh --tmp-dir /work -o /work/squashed.tar myapp:latest