I'm trying to build a new Docker image for our development process, using cpanm
to install a bunch of Perl modules as a base image for various projects.
While developing the Dockerfile, cpanm
returns a failure code because some of the modules did not install cleanly.
I'm fairly sure I need to get apt
to install some more things.
My question is, where can I find the /.cpanm/work
directory quoted in the output, in order to inspect the logs? In the general case, how can I inspect the file system of a failed docker build
command?
Morning edit After biting the bullet and running a find
I discovered
/var/lib/docker/aufs/diff/3afa404e[...]/.cpanm
Is this reliable, or am I better off building a "bare" container and running stuff manually until I have all the things I need?
Debugging build step failures is indeed very annoying.
The best solution I have found is to make sure that each step that does real work succeeds, and adding a check after those that fails. That way you get a committed layer that contains the outputs of the failed step that you can inspect.
A Dockerfile, with an example after the
# Run DB2 silent installer
line:Everytime docker successfully executes a
RUN
command from a Dockerfile, a new layer in the image filesystem is committed. Conveniently you can use those layers ids as images to start a new container.Take the following Dockerfile:
and build it:
You can now start a new container from
00f017a8c2a6
,044e1532c690
and5bd8172529c1
:of course you might want to start a shell to explore the filesystem and try out commands:
When one of the Dockerfile command fails, what you need to do is to look for the id of the preceding layer and run a shell in a container created from that id:
Once in the container:
If you really need to experiment in the actual layer that failed instead of working from the last working layer, see Drew's answer.
Docker caches the entire filesystem state after each successful
RUN
line.Knowing that:
RUN
command, comment it out in the Dockerfile (as well as any and all subsequentRUN
commands), then rundocker build
anddocker run
again.RUN
command, simply add|| true
to it to force it to succeed; then proceed like above (keep any and all subsequentRUN
commands commented out, rundocker build
anddocker run
)Tada, no need to mess with Docker internals or layer IDs, and as a bonus Docker automatically minimizes the amount of work that needs to be re-done.
What I would do is comment out the Dockerfile below and including the offending line. Then you can run the container and run the docker commands by hand, and look at the logs in the usual way. E.g. if the Dockerfile is
and it's dying at bar I would do
Then
The top answer works in the case that you want to examine the state immediately prior to the failed command.
However, the question asks how to examine the state of the failed container itself. In my situation, the failed command is a build that takes several hours, so rewinding prior to the failed command and running it again takes a long time and is not very helpful.
The solution here is to find the container that failed:
Commit it to an image:
And then run the image [if necessary, running bash]:
Now you are actually looking at the state of the build at the time that it failed, instead of at the time before running the command that caused the failure.