1

I am aware of two ways of creating Docker images:

  1. Build the image using a Dockerfile
  2. Use docker commit <container_id> against a running container with changes.

I find changing a Dockerfile each time I need image changes to be awfully inconvenient. Instead I have taken to launching ephemeral containers with docker run, installing packages I need on the fly with sudo, then committing the image.

I didn't realize however there is a footgun involved in this approach, especially if you frequently use and switch up docker run hacks. I launch containers with changing bind mounts, environment variables, differing networks, etc. A lot of that seems to be considered part of the configuration of the container, and is committed in docker commit alongside actual filesystem changes.

For example if you do:

docker run --env FOO=BAR --name container_name ubuntu:focal
docker commit container_name new_image
docker run -it new_image
echo $FOO

You will see that the env variable FOO is now a part of new_image.

This creates some awfully confusing situations, as I consider arguments to docker run to be as ephemeral as the container it creates. I am only concerned about persisting package installs.

I would like to commit just the actual image, just the file system changes. Is there any way to do that?

2
  • 1
    The way to go is as you said to write a Dockerfile. Why do you find it inconvenient? It should be roughly just adding some RUN ... directives similar to what you do manually when running the initial container.
    – Gaël J
    Mar 15, 2022 at 19:50
  • This has been answered in another thread: stackoverflow.com/questions/18952572/…
    – cmsmith7
    Apr 5, 2022 at 16:03

3 Answers 3

0

Share us an example of your recurring "image changes". I think your problem is not with docker, is with the architecture of your application.

  • Data changes should be handled using a database not the file system.
  • Source code changes, should be managed with a git repository and the respective new build, generating a new image version ready to be deployed
  • Infrastructure changes should be ... That's what Docker was created for. You should modify the Dockerfile, push the changes, build a new image, etc
  • Configurations should be managed with environment variables manually injected at docker run or using some external service like consul, configurator, etc
  • If your application needs to upload or download files like images, reports, etc, you should use a specialized service like aws s3, gcp Filestore, some open source, etc

As you can see, you don't need a huge native backup with docker commit.

0

You could try giving docker commit --change a try.

docker run --env FOO=BAR <image>
docker commit --change "ENV FOO=SETVALUE" <container_from_image> <new_image_tagged_from_state_of_container>

Please note that docker's engine specifies that "If the operator names an environment variable without specifying a value, then the current value of the named variable is propagated into the container’s environment" so you'll need to set the environment variable to something such as SETVALUE

0

Buildah

This creates some awfully confusing situations, as I consider arguments to docker run to be as ephemeral as the container it creates. I am only concerned about persisting package installs.

Sure does. Don't use docker. =) Docker is just one method of creating an image. It blurs the line between and online (hot container) and offline build process. Instead try buildah, which works with any shell. No dockerfile needed, also runs rootless. Try the below with buildah unshare ./image.sh

#!/bin/bash
# Call this script image.sh
# Invoke as regular user with `buildah unshare ./image.sh`
ctr=$(buildah from alpine:3)
mnt=$(buildah mount "$ctr")

echo "Created offline container $ctr"
echo "Got mount $mnt"

# write/copy/move directly into $mnt
echo "Write directly into mount" > "$mnt/foo.txt"

temp=$(mktemp)
echo "Created temp $temp"
echo foo > "$temp"
mv "$temp" "$mnt/bar"

echo "No container running"

buildah run "$ctr" /bin/sh <<-EOF
  echo "Hello from inside container.";
  apk update;
  apk add podman;
  echo 42 > baz;
EOF

buildah config                     \
  --author "Joe Doe <[email protected]>" \
  --label "apples=oranges"         \
  --env "foo=bar"                  \
  "$ctr";

buildah commit "$ctr" mynewimage

You can see what that includes

podman run -i mynewimage /bin/sh <<-"EOF"
  echo -e "\nfoo:"
  cat foo

  echo -e "\nbar:"
  cat bar

  echo -e "\nbaz:"
  cat baz

  echo -e "\nenv"
  env
EOF

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.