aaa90210
aaa90210

Reputation: 12083

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 command.

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!

Upvotes: 475

Views: 446091

Answers (14)

Ali Rasouli
Ali Rasouli

Reputation: 1905

Your command must be in Dockerfile. For example if you have a docker image with docker image name "mydockerimg" with tag "v1". You must follow below steps:

sudo mkdir mynewimage
sudo cd mynewimage
sudo nano Dockerfile

Then copy bellow line into Dockerfile

from mydockerimg:v1
WORKDIR /App
ENTRYPOINT ["command1", "option1","option2","option3","option4"]
ENTRYPOINT ["command2", "option1","option2","option3"]
ENTRYPOINT ["command3", "option1","option2","option3","option4","option5"]
ENTRYPOINT ["command4", "option1"]

Then ctrl+o then enter(for save nano tool) Then ctrl+x(for exit from nano tool) Then you must run below commands:

sudo docker build . -t mydockerimg:v2
sudo docker run -it -td mydockerimg:v2

Congratulation! You did it.

Your docker container with your wanted starting command is created.

Upvotes: 0

Dmitriusan
Dmitriusan

Reputation: 12369

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

Upvotes: 648

Bryce Rakop
Bryce Rakop

Reputation: 184

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

  1. Copy the file you horked out of the image:

    docker cp bt-php:/etc/apache2/apache2.conf .

  2. Fix it locally

  3. Copy it back in

    docker cp apache2.conf bt-php:/etc/apache2/apache2.conf

  4. Start your container back up

  5. *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!

Upvotes: 2

aaa90210
aaa90210

Reputation: 12083

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).

Upvotes: 200

Travis
Travis

Reputation: 572

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. :)

Upvotes: 1

BrendenCom
BrendenCom

Reputation: 89

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

Upvotes: 8

Richard Nienaber
Richard Nienaber

Reputation: 21

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.

Upvotes: 2

Summer
Summer

Reputation: 91

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

Upvotes: 4

John
John

Reputation: 7826

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:

  1. cd /var/lib/docker/overlay2/
    
  2. find | grep somechangedfile 
    # You now can see the changed file from your container in a hexcoded folder/diff
    
  3. cd hexcoded-folder/diff
    
  4. 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
    
  5. 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.

Upvotes: 2

Saurabh Kumar
Saurabh Kumar

Reputation: 2763

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

Upvotes: 2

Lars Christian Jensen
Lars Christian Jensen

Reputation: 1632

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

Upvotes: 7

Amit Dudhbade
Amit Dudhbade

Reputation: 61

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

Upvotes: 2

Dean Rather
Dean Rather

Reputation: 32374

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.

Upvotes: 5

Ethan T
Ethan T

Reputation: 1480

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.

Upvotes: 34

Related Questions