I have a script startScript.sh that I want to run after the docker container completely starts (including loading all services that the container is supposed to start)
After that I want to run a script: startScript.sh
This is what I do:
sudo docker run -p 8080:8080 <docker image name> " /bin/bash -c ./startScript.sh"
However this gives me an error:
WFLYSRV0073: Invalid option '/bin/bash'
Even tried different shells still same error. Even tried passing just the script file name. Still did not help.
Note: I know that the above file is in the container in the root folder: /
In fact I once entered the container by doing: sudo docker exec and manually ran that script file and it worked.
But when I try to automatically do it as above, it does not work for me.
Some questions:
1. Please suggest what could be the issue.
2. I want to run that script after the container has started completely and is up and running - including all the services that are part of it. Is this the right way to even do it? Or does this try to run while the container is starting up?
When you pass arguments after the image name, you are not modifying the entrypoint, but the command (CMD). It seems your image has WFLYSRV0073 as entrypoint, which makes the actual executed binary be your entrypoint, with your command as arguments. Which makes WFLYSRV0073 fail when trying to parse /bin/bash as an argument.
To run just your script, you could override the image's entrypoint with an empty string, making it run your command's first element. Notice I also remove the quotes, or else Docker will search for a binary with the name containing spaces, which of course doesn't exist.
sudo docker run --entrypoint "" -p 8080:8080 <docker image name> /bin/bash -c ./startScript.sh
However this is probably not what you want: it won't run what the image should actually be running, only your setup script. The correct thing to do here is to modify the image's Dockerfile to run the setup script as the entrypoint, and at the end of it run the script's current entrypoint (the actual thing you want to run).
Alternatively, if you do not control the image you are running, you can use FROM <the current image> in a new Dockerfile to build another image based on it, setting the entrypoint to your script.
Edit:
An example of how the above can be done can be seen in MariaDB's entrypoint: you first start a temporary server, run your setup, then restart it, running the definitive service (which is the CMD) at the end.
The above solutions are good in case you want to perform initialization for an image, but if you just want to be able to run a script for development reasons instead of doing it consistently on the image's entrypoint, you can copy it to your container and then use docker exec <container name> your-command and-arguments to run it.
I am trying to start a docker container using the ubuntu image:
docker container run -d --name ubuntu_assignment_4 6e4f1fe62
However as soon as I start the container it stops again.
Why does this happen and how can I ensure the container stays running?
The image I am trying to run here is: ubuntu:14.04
If you are going to use the ubuntu:14.04 image without any modifications to it, you would not require a separate Dockerfile. And it is not possible to keep the plain ubuntu:14.04 image running as a container.
You can directly launch the container with an interactive shell using the ubuntu:14.04 image.
docker run -it ubuntu:14.04 /bin/bash
But the plain ubuntu:14.04 image does not have curl pre-installed on it.
You will need a custom Dockerfile for this.
I can't say exactly what is happening without seeing the complete Dockerfile that was used to build the image, but I am pretty certain that the trouble you are having is just because whatever task that is being started inside the container is finishing and exiting.
Docker containers work by having some command assigned (using ENTRYPOINT or CMD directives in the Dockerfile, or as an argument to docker start or docker run on the command line) which is the program that is started when the container loads. The container will live for as long as that task continues to run, and once that program finishes the container will terminate.
To specify the startup entrypoint at the command line, try:
docker create -it [image] /bin/bash
Then start it like this:
docker start -ia [Container ID]
The container will exit once the shell exits, because this is assigning the shell as the entry point.
cURL may not be installed by default. It is possible to install it using apt-get. But again, once the shell is closed, the container will stop and any changes will be lost. As a start, try creating a new directory somewhere, and then add a file called Dockerfile with this content:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl
ENTRYPOINT ["/bin/bash"]
That will create a new image with curl installed. then, from inside the new directory where the Dockerfile was created, use:
docker build .
docker images
which will build a new image, using the Dockerfile as the blueprint.
Once the build finishes, find the image ID for the new container, and run it using:
docker run -it [image id]
Ultimately, to make Docker really useful, the typical approach is to replace that last line in the Dockerfile (ENTRYPOINT ["command"]) with something that will continue running forever (like ENTRYPOINT ["apache2"] or ENTRYPOINT ["redis"] or similar). If you have experience using regular desktop/server OS installs, and full virtual machines like VMWare or VirtualBox, just remember that Docker is very different; the way it works and the patterns used to deploy it are not the same.
I am using docker image opencv from https://hub.docker.com/r/andrewssobral/bgslibrary_opencv3/
of andrewssobral author.
First, i initialized container of the image by typing command:
docker run -it -p 5901:5901 andrewssobral/bgslibrary_opencv3 bash
And i tried install vim by command line:
apt-get install vim
But when i use exit COMMAND to go out of the container and i run it again then vim was uninstalled.
So how do i install vim or another software permanently inside docker?
But when i exit docker above container and i run it again then vim was uninstalled.
This is where the problem is: docker run creates a new container.
When you use docker run ... a new container is created and started based on the image you provide inside the command. It is also assigned a random name (if you don't specify one). If this container exits, you can then use docker start name and start it again. This means that if you had previously installed vim it will be there.
Solution: create a new image which includes what you need.
#Sergiu proposed to use Dockerfile
or another way is to save the current state of your container to a new image so that you can use it later on to create new containers with your changes included. To do this you can use docker commit
something like this:
docker commit your_modified_container_name [REPOSITORY[:TAG]]
You have two options: or you edit the Dockerfile provided by the author to add vim or you create a new Dockefile FROM the image.
How can I debug docker container that I set to always restart.
I have a container that launch nodejs app, with a
CMD ["nodemon", "/usr/src/app/app.js »] that work very well on other container but not on the new one i created it says with docker logs containerName :
Usage: nodemon [nodemon options] [script.js] [args]
See "nodemon --help" for more.
How can I connect to the container to have more informations than logs, for example see some config file or if my nodejs files have been copied.
I didn’t find a way : I would like to use docker exec -it bash and navigate in my docker but because it is always restarting I cannot. How to debug this kind of container ?
EDIT : i use the CMD["bash"] but when i use docker exec -it bash i doesn't work
Because the container keep restarting.
You could make a new image base on your container image, and a different starting script (one which runs the node command for testing, and then opens a bash for instance)
You could need to COPY that script
COPY myscript /usr/local/bin
CMD ["/usr/local/bin/myscript"]
That way, you can test your current image as wrapped in a test image.
You can even only use bash in that new image
CMD["bash"]
And launch the command manually.
For that, you would need to run that image with:
docker run -it --rm myNewImage
That will open an interactive bash session.
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. :)