Check the File in Exited Container - docker

I have an issue invoking the script to start the container. I think I'd better first find a way to tell if the script is actually located in the right place. But neither docker exec nor docker attach seems to allow me to get into an exited container.
I also tried docker run -it --volumes-from [exited_container_id] ubuntu. I thought I might be able to see the file system in ubuntu but I cannot find the mounting point. Is there any way for me to login to an exited container and see the files that I ADDed?

You can check if the script is located in the right place adding a RUN ls -l / line in your Dockerfile and building the image
FROM frolvlad/alpine-oraclejdk8:slim
ADD build/libs/zuul*.jar /app.jar
ADD src/main/script/startup.sh /startup.sh
RUN ls -lah /
EXPOSE 8080 8999
ENTRYPOINT ["/startup.sh"]
Then just build the Dockerfile
docker build -t myapp .
You should see the result of that ls in the output of the build

Related

understanding docker : how come my docker container content is dynamic?

I want to make sure I understand correctly docker: when i build an image from the current directory I run:
docker build -t imgfile .
What happens when i change the content of a file in the directory AFTER the image is built? From what i've tried it seems it changes the content of the docker image also dynamically.
I thought the docker image was like a zip file that could only be changed with docker commands or logging into the image and running commands.
The dockerfile is :
FROM lambci/lambda:build-python3.8
WORKDIR /var/task
EXPOSE 8000
RUN echo 'export PS1="\[\e[36m\]zappashell>\[\e[m\] "' >> /root/.bashrc
CMD ["bash"]
And the docker run command is :
docker run -ti -p 8000:8000 -e AWS_PROFILE=zappa -v "$(pwd):/var/task" -v ~/.aws/:/root/.aws --rm zappa-docker-image
Thank you
Best,
Your docker run command isn't really running your image at all. The docker run -v $(pwd):/var/task syntax overwrites what was in /var/task in the image with a bind mount to the current directory on the host. So when you edit a file on your host, the container has the same host directory (and not the content from the image) and you see the changes inside the container as well.
You're right that the image is immutable. The image you show doesn't really contain anything, beyond a .bashrc file that won't usually be used. You can try running the image without the -v options to see:
docker run --rm zappa-docker-image ls -al
# just shows `.` and `..` directories
I'd recommend making sure you COPY your application into the image, setting its CMD to actually run the application, and removing the -v option that overwrites its main directory. If your goal is to run host code against host files with host supporting data like your AWS credentials, you're not really getting much benefit from introducing Docker in between your application and every single file it uses.

Can not run docker container?

I use docker build -t iot . to build a image
my Dockerfile is :
FROM centos
USER root
ADD jdk1.8.0_101.tar.gz /root
COPY run.sh /etc
RUN chmod 755 /etc/run.sh
CMD "/etc/run.sh"
my run.sh is:
#!/bin/bash
echo "aaaa"
I use docker run -itd iot to run a container,but I find my container can not be run.
what should I do?
Your image builds and runs correctly. You just need to remove the d flag from run (for detached) or the docker command will exit immediately and run your container in the background. You can see that it actually exited with code zero according to the status column in docker ps -a.
You can corroborate this by running docker logs d63a (which is your container id). You should see aaaa.
Your description is inaccurate. When you docker run the container, it normally started, printed aaaa, and then exited.
So I guess what you would ask is "why my container cannot keep running, such as a daemon process". This is because you're executing a shell script which is actually a one-shot thing. Modify the CMD line in your Dockerfile to CMD "bash", your container will then not exit.

Attaching to a docker container with base image scratch?

I have a docker file as follows:
FROM scratch
ARG VERSION=NOT_SET
ENV VERSION $VERSION
COPY foobar foobar
COPY foobar-*.yaml /etc/
COPY jwt/ /etc/jwt/
EXPOSE 8082
ENTRYPOINT ["./foobar"]
CMD ["-config", "/etc/foobar-local.yaml"]
Now, docker ps shows the following:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
653a9b287eb6 7693481.dkr.ecr.us-east-1.amazonaws.com/foobar:0.0.1 "./foobar -config /e" About a minute ago Up About a minute foobar
When I try to exec to this container with the following command:
sudo docker exec -it 653a9b287eb6 /bin/bash
it shows the following error:
rpc error: code = 2 desc = oci runtime error:
exec failed: exec: "/bin/bash": stat /bin/bash: no such file or directory
You need to add a shell to your empty base image (SCRATCH) in order to attach to it.
Right now, your image only include an executable, which is not enough.
As mentioned in issue 17896
FROM scratch literally is an empty, zero-byte image / filesystem, where you add everything yourself.
See for example, the hello-world which, produces an image that's 860 bytes total.
If you need a shell to attach to it through docker exec, start from a small image like Alpine (which has only /bin/sh though: you would need apk add bash to add bash, as commented below by user2915097).
If you are using Kubernetes, I have a repo that installs busybox on FROM scratch -image: https://github.com/phzfi/scratch-debug
In principle, by using the same process, you can also install busybox and shell on any other docker container, but I need to still make a script for debugging e.g. docker-compose and swarm orchestrators.

docker: Only execute command in when container is running

I want to create a backup of a mount volume in my docker container.
This is the command in my dockerfile:
RUN tar -cvpzf test.tar -C /test/ .
But the problem is that it can only be executed after the mount of my volume. (because my volume will be mounted to /test/
So this command needs to be executed after starting the docker container and not when I'm creating the image. How do I have to perform this?
Thanks
Once your container is running, assuming the container has tar, you can do exactly what you want with:
docker exec nameofcontainer [options] tar -cvpzf test.tar -C /test/ .
You can get the names of running containers using docker ps. For options, you may want to use -ti so that you can see the output.
You could also build the container with a custom ENTRYPOINT or CMD which will both start whatever the primary job of the container is going to be and run your backup script, as well as any other tasks that need performing.
The official mysql container does something like this, with the docker-entrypoint.sh script.

How to start a stopped Docker container with a different command?

I would like to start a stopped Docker container with a different command, as the default command crashes - meaning I can't start the container and then use 'docker exec'.
Basically I would like to start a shell so I can inspect the contents of the container.
Luckily I created the container with the -it option!
Find your stopped container id
docker ps -a
Commit the stopped container:
This command saves modified container state into a new image named user/test_image:
docker commit $CONTAINER_ID user/test_image
Start/run with a different entry point:
docker run -ti --entrypoint=sh user/test_image
Entrypoint argument description:
https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime
Note:
Steps above just start a stopped container with the same filesystem state. That is great for a quick investigation; but environment variables, network configuration, attached volumes and other stuff is not inherited. You should specify all these arguments explicitly.
Steps to start a stopped container have been borrowed from here: (last comment) https://github.com/docker/docker/issues/18078
Edit this file (corresponding to your stopped container):
vi /var/lib/docker/containers/923...4f6/config.json
Change the "Path" parameter to point at your new command, e.g. /bin/bash. You may also set the "Args" parameter to pass arguments to the command.
Restart the docker service (note this will stop all running containers unless you first enable live-restore):
service docker restart
List your containers and make sure the command has changed:
docker ps -a
Start the container and attach to it, you should now be in your shell!
docker start -ai mad_brattain
Worked on Fedora 22 using Docker 1.7.1.
NOTE: If your shell is not interactive (e.g. you did not create the original container with -it option), you can instead change the command to "/bin/sleep 600" or "/bin/tail -f /dev/null" to give you enough time to do "docker exec -it CONTID /bin/bash" as another way of getting a shell.
NOTE2: Newer versions of docker have config.v2.json, where you will need to change either Entrypoint or Cmd (thanks user60561).
Add a check to the top of your Entrypoint script
Docker really needs to implement this as a new feature, but here's another workaround option for situations in which you have an Entrypoint that terminates after success or failure, which can make it difficult to debug.
If you don't already have an Entrypoint script, create one that runs whatever command(s) you need for your container. Then, at the top of this file, add these lines to entrypoint.sh:
# Run once, hold otherwise
if [ -f "already_ran" ]; then
echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
cat
fi
touch already_ran
# Do your main things down here
To ensure that cat holds the connection, you may need to provide a TTY. I'm running the container with my Entrypoint script like so:
docker run -t --entrypoint entrypoint.sh image_name
This will cause the script to run once, creating a file that indicates it has already run (in the container's virtual filesystem). You can then restart the container to perform debugging:
docker start container_name
When you restart the container, the already_ran file will be found, causing the Entrypoint script to stall with cat (which just waits forever for input that will never come, but keeps the container alive). You can then execute a debugging bash session:
docker exec -i container_name bash
While the container is running, you can also remove already_ran and manually execute the entrypoint.sh script to rerun it, if you need to debug that way.
I took #Dmitriusan's answer and made it into an alias:
alias docker-run-prev-container='prev_container_id="$(docker ps -aq | head -n1)" && docker commit "$prev_container_id" "prev_container/$prev_container_id" && docker run -it --entrypoint=bash "prev_container/$prev_container_id"'
Add this into your ~/.bashrc aliases file, and you'll have a nifty new docker-run-prev-container alias which'll drop you into a shell in the previous container.
Helpful for debugging failed docker builds.
This is not exactly what you're asking for, but you can use docker export on a stopped container if all you want is to inspect the files.
mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR
docker-compose run --entrypoint /bin/bash cont_id_or_name
(for conven, put your env, vol mounts in the docker-compose.yml)
or use docker run and manually spec all args
It seems docker can't change entry point after a container started. But you can set a custom entry point and change the code of the entry point next time you restart it.
For example you run a container like this:
docker run --name c --entrypoint "/boot" -v "./boot":/boot $image
Here is the boot entry point:
#!/bin/bash
command_a
When you need restart c with a different command, you just change the boot script:
#!/bin/bash
command_b
And restart:
docker restart c
My Problem:
I started a container with docker run <IMAGE_NAME>
And then added some files to this container
Then I closed the container and tried to start it again withe same command as above.
But when I checked the new files, they were missing
when I run docker ps -a I could see two containers.
That means every time I was running docker run <IMAGE_NAME> command, new image was getting created
Solution:
To work on the same container you created in the first place run follow these steps
docker ps to get container of your container
docker container start <CONTAINER_ID> to start existing container
Then you can continue from where you left. e.g. docker exec -it <CONTAINER_ID> /bin/bash
You can then decide to create a new image out of it
I have found a simple command
docker start -a [container_name]
This will do the trick
Or
docker start [container_name]
then
docker exec -it [container_name] bash
I had a docker container where the MariaDB container was continuously crashing on startup because of corrupted InnoDB tables.
What I did to solve my problem was:
copy out the docker-entrypoint.sh from the container to the local file system (docker cp)
edit it to include the needed command line parameter (--innodb-force-recovery=1 in my case)
copy the edited file back into the docker container, overwriting the existing entrypoint script.
To me Docker always leaves the impression that it was created for a hobby system, it works well for that.
If something fails or doesn't work, don't expect to have a professional solution.
That said: Docker does not only NOT support such basic administrative tasks, it tries to prevent them.
Solution:
cd /var/lib/docker/overlay2/
find | grep somechangedfile
# You now can see the changed file from your container in a hexcoded folder/diff
cd hexcoded-folder/diff
Create an entrypoint.sh (make sure to backup an existing one if it's there)
cat > entrypoint.sh
#!/bin/bash
while ((1)); do sleep 1; done;
Ctrl+C
chmod +x entrypoint.sh
docker stop
docker start
You now have your docker container running an endless loop instead of the originally entry, you can exec bash into it, or do whatever you need.
When finished stop the container, remove/rename your custom entrypoint.
It seems like most of the time people are running into this while modifying a config file, which is what I did. I was trying to bypass CORS for a PHP/Apache server with a Vue SPA as my entry point. Anyway, if you know the file you horked, a simple solution that worked for me was
Copy the file you horked out of the image:
docker cp bt-php:/etc/apache2/apache2.conf .
Fix it locally
Copy it back in
docker cp apache2.conf bt-php:/etc/apache2/apache2.conf
Start your container back up
*Bonus points - Since this file is being modified, add it to your Compose or Build scripts so that when you do get it right it will be baked into the image!
Lots of discussion surrounding this so I thought I would add one more which I did not immediately see listed above:
If the full path to the entrypoint for the container is known (or discoverable via inspection) it can be copied in and out of the stopped container using 'docker cp'. This means you can copy the original out of the container, edit a copy of it to start a bash shell (or a long sleep timer) instead of whatever it was doing, and then restart the container. The running container can now be further edited with the bash shell to correct any problems. When finished editing another docker cp of the original entrypoint back into the container and a re-restart should do the trick.
I have used this once to correct a 'quick fix' that I butterfingered and was no longer able to run the container with the normal entrypoint until it was corrected.
I also agree there should be a better way to do this via docker: Maybe an option to 'docker restart' that allows an alternate entrypoint? Hey, maybe that already works with '--entrypoint'? Not sure, didn't try it, left as exercise for reader, let me know if it works. :)

Resources