Remove docker image depending on an already removed image - docker

So, I have been doing something I knew would end up bad, I used the docker rm -f flag to remove an image B because it kept on complaining that another image A was still using it and I didn't find that specific image A, couldn't see it, so I thought, I'll use '-f'.
Unfortunately, of course it did exist, and now I cannot remove image A anymore because I removed its dependency image B and I keep on getting
Error response from daemon: No such id <id-of-already-removed-image-with--f-option>
error: failed to remove one or more images
when I try to remove it.
So basically, can I remove this image that points to an image that's not present anymore?

Switched off docker through
service docker.io stop
changed the DOCKER_OPTS in /etc/default/docker.io to
DOCKER_OPTS="--graph=/home/kasper/dockerrepo"
restarted docker through
service docker.io start
and then removed Var/lib/docker. Didn't figure out a finer grained way of cleaning this up.

Related

Remove docker image if it exists

I have a debian package I am deploying that comes with a docker image. On upgrading the package, the prerm script stops and removes the docker image. As a fail safe, I have the preinst script do it as well to ensure the old image is removed before the installation of the new image. If there is no image, the following error reports to the screen: (for stop) No such image: <tag> and (for rmi): No such container: <tag>.
This really isn't a problem, as the errors are ignored by dpkg, but they are reported to the screen, and I get constant questions from the users is that error ok? Did the install fail? etc.
I cannot seem for find the correct set of docker commands to check if a container is running to stop it, and check to see if an image exists to remove it, so those errors are no longer generated. All I have is docker image tag to work with.
I think you could go one of two ways:
Knowing the image you could check whether there is any container based on that image. If yes, find out whether that container is running. If yes, stop it. If not running, remove the image. This would prevent error messages showing up but other messages regarding the container and image handling may be visible.
Redirect output of the docker commands in question, e.g. >/dev/null
you're not limited with docker-cli you know? you can always combine docker-cli commands with linux sh or dos commands as well and also you can write your own .sh scripts and if you don't want to see the errors you can either redirect them or store them to a file such as
to redirect: {operation} 2>/dev/null
to store : {operation} 2>>/var/log/xxx.log

New Keycloak image with own changes crashes directly

I have a weird problem with Docker and hope someone here can help me :)
I want to create a keycloak image that is derived from the image jboss/keycloak. The idea is that in the Dockerfile also a preconfigured standalone.xml is copied into the image and keycloak can start directly without manual work.
But as soon as I write for example a
"CMD touch /opt/test.txt"
into the file the container crashes with the message "12:02:14,290 INFO [org.jboss.modules] (main) JBoss Modules version 1.9.1.Final
WFLYSRV0073: Invalid option '/bin/sh'"
This is just a new file with no purpose, the changes to the .xml are not in there yet.
As soon as I put only the FROM back in and rebuild everything works again.
I thought through the layers in the container you could mod an image, but here it doesn't seem to work. Can someone tell me why ?
So far it has always worked with the alpine image, but I don't want to build the whole keycloak setup again myself, when there is already an official image for it.
This is basically what I had in mind:
FROM jboss/keycloak:X.XX
CMD rm /opt/jboss/keycloak/standalone/configuration/standalone.xml
COPY ./keycloak/standalone.xml /opt/jboss/keycloak/standalone/configuration/
Thanks for help :)
Change
CMD rm
to
RUN rm
RUN is part of building. every RUN command is executed while your image is built.
With CMD you define (or override) the default command when running/starting a container based on your image (and you don't want to change keycloaks default CMD)

Need to remove symbolic link I created for /var/lib/docker/ but can't find it. Unable to use docker and feel helpless

I'm feeling really terrible atm so any help would be really appreciated. I kept running out of space when downloading docker images on /var, so I decided I needed to change the location for where docker was installing images. I tried several methods but had no success. First, I tried creating daemon.json in etc/docker and mapping data-root to a place with more storage (data2/docker). I stopped docker, moved everything over, made the file, but no dice. The docker daemon wouldn't start.
Then, I saw this method https://stackoverflow.com/a/49743270/13034460 which involves creating a symbolic link between /var/lib/docker and the new directory (data2/docker). I followed his instructions:
Much easier way to do so:
Stop docker service: sudo systemctl stop docker
Move existing docker directory to new location sudo mv /var/lib/docker/ /path/to/new/docker/
Create symbolic link
sudo ln -s /path/to/new/docker/ /var/lib/docker
Start docker service
sudo systemctl start docker
Well, this didn't work for me. I can't find the error message b/c it's too far up in my terminal, but it was along the lines of "you don't have enough storage/we don't know where to store this image". /data2/docker should have tons of storage so that can't be the issue.
But the big problem now is that this symbolic link exists and I can't figure out how to get rid of it. I tried removing everything related to docker on the computer, uninstalling, then reinstalling docker (which always used to work for me if there were any issues). But when I reinstall, it won't even run docker hello-world b/c of the link (I think). I get a message:
docker: open /data2/docker/tmp/GetImageBlob289478576: no such file or directory
So...it's looking in data2/docker because of the symbolic link (I assume), but that directory doesn't exist anymore. But neither does /var/lib/docker! All I want is to delete this link and get everything back to fresh defaults. I can worry about the storage issue another time. If I can't use docker at all, I'm so screwed. I've tried looking in every directory to find the link using -ls -l, but I can't find it. I used the exact code that the above references when I created the link (just my paths instead).
I would be so grateful to anyone who could help--I'm so lost on this. Thank you!

How do I update docker images?

I read that docker works with layers, so when creating a container with a Dockerfile, you start with the base image, then subsequent commands run add a layer to the container, so if you save the state of that new container, you have a new image. There are a couple of things I'm wondering about this.
If I start from a Ubuntu image, which is pretty big and bulky since its a complete OS, then I add a few tools to it and save this as a new image which I upload to the hub. If someone downloads my image, and they already have a Ubuntu image saved in their images folder, does this mean they can skip downloading Ubuntu since they already have the image? If so, how does this work when I modify parts of the original image, does Docker use its cached data to selectively apply those changes to the Ubuntu image after it loads it?
2.) How do I update an image that I built by modifying the Dockerfile? I setup a simple django project with this Dockerfile:
FROM python:3.5
ENV PYTHONBUFFERED 1
ENV APPLICATION_ROOT /app
ENV APP_ENVIRONMENT L
RUN mkdir -p $APPLICATION_ROOT
WORKDIR $APPLICATION_ROOT
ADD requirements.txt $APPLICATION_ROOT
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ADD . $APPLICATION_ROOT
and used this to create the image in the beginning. So everytime I create a box, it loads all these environment variables, if I rebuild the box completely it reinstalls the packages and all the extras. I need to add a new environment variable, so I added it to the bottom of the Dockerfile, along with a test variable:
ENV COMPOSE_CONVERT_WINDOWS_PATHS 1
ENV TEST_ENV_VAR TEST
When I delete the container and the image, and build a new container, it all seems to go accordingly, it tells me that it creates the new Step 4 : ENV
COMPOSE_CONVERT_WINDOWS_PATHS 1
---> Running in 75551ea311b2
---> b25b60e29f18
Removing intermediate container 75551ea311b2
So its like something gets lost in some of these intermediate container transitions. Is this how the caching system works, every new layer is an intermediate container? So with that in mind, how do you add a new layer, do you always have to add the new data at the bottom of the Dockerfile? Or would it be better to leave the Dockerfile alone once the image is built, and just modify the container and built a new image?
EDIT I just tried installing an image, a package called bwawrik/bioinformatics, which is a CentOS based container which has a wide range of tools installed.
It froze half way through, so I exited it and then ran it again to see if everything was installed:
$ docker pull bwawrik/bioinformatics
Using default tag: latest
latest: Pulling from bwawrik/bioinformatics
a3ed95caeb02: Already exists
a3ed95caeb02: Already exists
7e78dbe53fdd: Already exists
ebcc98113eaa: Already exists
598d3c8fd678: Already exists
12520d1e1960: Already exists
9b4912d2bc7b: Already exists
c64f941884ae: Already exists
24371a4298bf: Already exists
993de48846f3: Already exists
2231b3c00b9e: Already exists
2d67c793630d: Already exists
d43673e70e8e: Already exists
fe4f50dda611: Already exists
33300f752b24: Already exists
b4eec31201d8: Already exists
f34092f697e8: Already exists
e49521d8fb4f: Already exists
8349c93680fe: Already exists
929d44a7a5a1: Already exists
09a30957f0fb: Already exists
4611e742e0b5: Already exists
25aacf0148db: Already exists
74da82504b6c: Already exists
3e0aac083b86: Already exists
f52c7e0ac000: Already exists
35eee92aaf2f: Already exists
5f6d8eb70885: Already exists
536920bfe266: Already exists
98638e678c51: Already exists
9123956b991d: Already exists
1c4c8a29cd65: Already exists
1804bf352a97: Already exists
aa6fe9359956: Already exists
e7e38d1250a9: Already exists
05e935c831dc: Already exists
b7dfc22c26f3: Already exists
1514d4797ffd: Already exists
Digest: sha256:0391808e21b7b5cc0eb44fc2dad0d7f5415115bdaafb4534c0b6a12efd47a88b
Status: Image is up to date for bwawrik/bioinformatics:latest
So it definitely installed the package in pieces, not all in one go. Are these pieces, different images?
image vs. container
First, let me clarify some terminology.
image: A static, immutable object. This is the thing you build when you run docker build using a Dockerfile. An image is not a thing that runs.
Images are composed of layers. an image might have only one layer, or it might have many layers.
container: A running thing. It uses an image as its starting template.
This is similar to a binary program and a process. You have a binary program on disk (such as /bin/sh), and when you run it, it is a process on your system. This is similar to the relationship between images and containers.
Adding layers to a base image
You can build your own image from a base image (such as ubuntu in your example). Some commands in your Dockerfile will create a new layer in the ultimate image. Some of those are RUN, COPY, and ADD.
The very first layer has no parent layer. But every other layer will have a parent layer. In this way they link to one another, stacking up like pancakes.
Each layer has a unique ID (the long hexadecimal hashes you have already seen). They can also have human-friendly names, known as tags (e.g. ubuntu:16.04).
What is a layer vs. an image?
Technically, each layer is also an image. If you build a new image and it has 5 layers, you can use that image and it will contain all 5 layers. If you run a container using the third layer in the stack as your image ID, you can do that too - but it would only contain 3 layers. The one you specify and the two that are its ancestors.
But as a matter of convention, the term "image" generally means the layer that has a tag associated. When you run docker images, it will show you all of the top-level images, and hide the layers beneath (but you can show them all with -a).
What is an intermediate container?
When docker build runs, it does all of its work inside of containers (naturally!) So if it encounters a RUN step, it will create a container from the current top layer, run the specified commands in there, and then save the result as a new layer. Then it will create a container from this new layer, run the next thing... etc.
The intermediate containers are only used for the build process, and are discarded after the build.
How layer filesystems work
You asked whether someone downloading your ubuntu-based image are only doing a partial download, if they already had the ubuntu image locally.
Yes! That's exactly right.
Every layer uses the layer beneath it as a base. The new layer is basically a diff between that layer and a new state. It's not a diff in the same way as a git commit might work, though. It works at the file level, not at a the line level.
Say you started from ubuntu, and you ran this Dockerfile.
FROM: ubuntu:16.04
RUN groupadd dan && useradd -g dan dan
This would result in a two layer image. The first layer would be the ubuntu image. The second would probably have only a handful of changes.
A newer copy of /etc/passwd with user "dan"
A newer copy of /etc/group with group "dan"
A new directory /home/dan
A couple of default files like /home/dan/.bashrc
And that's it. If you start a container from this image, those few files would be in the topmost layer, and everything else would come from the filesystem in the ubuntu image.
The top-most read-write layer in a container
One other point. When you run a container, you can write files in the filesystem. But if you stop the container and run another container from the same image, everything is reset. So where are the files written?
Images are immutable, so once they are created, they can't be changed. You can build a new version, but that's a new image. It would have a different ID and would not be the same image.
A container has a top-level read-write layer which is put on top of the image layers. Any writes happen in that layer. It works just like the other layers. If you need to modify a file (or add one, or delete one), that is done in the top layer, and doesn't affect the lower layers. If the file exists already, it is copied into the read-write layer, and then modified. This is known as copy-on-write (CoW).
Where to add changes
Do you have to add new things to the bottom of Dockerfile? No, you can add anything anywhere (or change anything).
However, how you do things does affect your build times because of how the build caching works.
Docker will try to cache results during builds. If it finds as it reads through Dockerfile that the FROM is the same, the first RUN is the same, the second RUN is the same... it will assume it has already done those steps, and will use cached results. If it encounters something that is different from the last build, it will invalidate the cache. Everything from that point on will be re-run fresh.
Some things will always invalidate the cache. For instance if you use ADD or COPY, those always invalidate the cache. That's because Docker only keeps track of what the build commands are. It doesn't try to figure out "is this version of the file I'm copying the same one as last time?"
So it is a common practice to start with FROM, then put very static things like RUN commands that install packages with e.g. apt-get, etc. Those things tend to not change a lot after your Dockerfile has been initially written. Later in the file is a more convenient place to put things that change more often.
It's hard to concisely give good advice on this, because it really depends on the project in question. But it pays to learn how the build caching works and try to take advantage of it.

How to restore docker images which are removed by `docker rmi` command?

I issued command docker rmi 0d20855ef162 to remove it. How to find it back?
I don't want to docker pull from the remote registry again, how?
The rest DELETE action is called by api/client/rmi.go#L34, which in turn calls daemon/image_delete.go#L226
daemon.Graph().Delete(img.ID)
That calls graph/graph.go#L364-L375 which does:
tmp, err := graph.mktemp()
os.Rename(graph.imageRoot(id), tmp)
// Remove the trashed image directory
return os.RemoveAll(tmp)
So it does appear to delete the files from the imageRoot folder (if there is no conflict, meaning if the image is not referenced by anything else).
In that case, the answer would be that you cannot find that image back without pulling it again.

Resources