I've built a Dockerfile which ends with compiling my (Golang) code and then running the compiled binary:
# Compile my Go code
RUN go build -o bin *.go
# Run the binary
CMD /root/src/whisky/bin
After building the image (docker build -t whisky .) I run the image (docker run --name whisky whisky_image) and the program starts to give output in the terminal.
When I run the program from my laptop I can always stop it using CTRL+C, but now it's running inside the container and hitting CTRL+C doesn't do anything. The container simply keeps giving output and nothing stops.
I can still stop the container from another terminal docker stop whisky, but I guess there should be a nicer way.
Does anybody know the recommended way to stop the command in the container or stop the whole container from the same terminal?
[EDIT]
From the answers given I learned I can run the container in detached mode using -d and then tail the container logs using docker logs container_id --follow. Although that works I prefer to run the container directly (in non-detached mode) because then I can't make the mistake of running it in the background and forgetting about it.
Does anybody know how I can run the container in a way that I can stop it from the same terminal by hitting CTRL+C?
you can use '-d' --> in detached mode
[EDIT]
To add. After that you can tail to logs using
docker logs container_id --follow
Allocate a pseudo-tty (-t) and then you can control output by hitting CTRL+C:
$ docker run --name whisky -t whisky_image
^C
But container will be still running, so add also stdin (-i):
$ docker run --name whisky -ti whisky_image
^C
But container will be still there (see docker ps -a - in exited status), so you may add cleanup flag --rm:
$ docker run --name whisky --rm -ti whisky_image
^C
See Docker run doc for more details.
you need to run your container using init
docker run --init --name whisky whisky_image
then kill it using Ctrl+C
the initwill start your program as PID 1
As mentionned ealier, there is 2 possibilities, the first, detaching the process (-d option) or use a TTY with Interactive mode (-ti option).
The detached version will allow you to work and manage the instance, but won't let you down it by pressing CTRL+C
The TTY version with an Interactive mode (-i) will.
So, docker run -it should do the trick
Docker Run reference and Docker Container process behaviors can also help
Try this:
# Compile my Go code
RUN go build -o bin *.go
# Run the binary
CMD ["/root/src/whisky/bin"]
This is the exec form. in this form your executable is being called directly.
What you used is the shell form which starts your process with /bin/sh -c. This form does not automatically pass signals to the child processes.
Dockerfile
FROM golang
WORKDIR /go/src/app
ADD . .
# Compile my Go code
RUN go build -o bin *.go
# Run the binary
CMD /go/src/app/bin
Go program
package main
import (
"fmt"
"time"
)
func main() {
for {
fmt.Println("\nWHISKY TIME: ", time.Now().String())
time.Sleep(time.Second)
}
}
Building the Container
╭─exadra37#exadra37-Vostro-470 ~/Developer/DevNull/stackoverflow
╰─➤ sudo docker build -t whisky .
Sending build context to Docker daemon 3.072kB
Step 1/5 : FROM golang
---> c4d6fdf2260a
Step 2/5 : WORKDIR /go/src/app
---> Using cache
---> ab35c58a3608
Step 3/5 : ADD . .
---> 320a51d3e579
Step 4/5 : RUN go build -o bin *.go
---> Running in 5db9f4a9cbe1
Removing intermediate container 5db9f4a9cbe1
---> e16b272606da
Step 5/5 : CMD /go/src/app/bin
---> Running in f66039aeb53a
Removing intermediate container f66039aeb53a
---> d453f9e10c49
Successfully built d453f9e10c49
Successfully tagged whisky:latest
Running the Container
╭─exadra37#exadra37-Vostro-470 ~/Developer/DevNull/stackoverflow
╰─➤ sudo docker run -it --name whisky whisky 137 ↵
WHISKY TIME: 2019-11-25 16:19:26.397705029 +0000 UTC m=+0.000041700
WHISKY TIME: 2019-11-25 16:19:27.399189969 +0000 UTC m=+1.001526690
WHISKY TIME: 2019-11-25 16:19:28.399392173 +0000 UTC m=+2.001728894
WHISKY TIME: 2019-11-25 16:19:29.399566682 +0000 UTC m=+3.001903403
^C%
As you can see I was able o stop it with CTRL + C, and I just needed to use the flags -it.
The flags used:
╭─exadra37#exadra37-Vostro-470 ~/Developer/DevNull/stackoverflow
╰─➤ docker run --help | grep "\-t, \-\-tty" - 2 ↵
-t, --tty Allocate a pseudo-TTY
╭─exadra37#exadra37-Vostro-470 ~/Developer/DevNull/stackoverflow
╰─➤ docker run --help | grep "\-i, \-\-interactive" -
-i, --interactive Keep STDIN open even if not attached
Restarting the container
╭─exadra37#exadra37-Vostro-470 ~/Developer/DevNull/stackoverflow
╰─➤ sudo docker start -i whisky
WHISKY TIME: 2019-11-25 16:21:03.159420042 +0000 UTC m=+0.000047654
WHISKY TIME: 2019-11-25 16:21:04.161264182 +0000 UTC m=+1.001891819
WHISKY TIME: 2019-11-25 16:21:05.161470301 +0000 UTC m=+2.002097939
^C%
When restarting the container we just need to use the flag -i, and you are still able to stop it with CTRL + C.
The flags used:
╭─exadra37#exadra37-Vostro-470 ~/Developer/DevNull/stackoverflow
╰─➤ docker start --help | grep "\-i, \-\-interactive" -
-i, --interactive Attach container's STDIN
To stop the whole container please use below commands.
$ docker stop <container>
The docker stop command stops running Docker containers.
It sends the SIGTERM signal to the running process inside the docker container and requests it to terminate.
Related
While the nginx might not be a good example for this case but there would be similar cases that we will need to run a process and access it inside a container without recreating/rerunning it.
I already run nginx as a container using following command:
docker run -d --name=my_container nginx:latest
I didn't active terminal or interactive mode during docker run command. Now, I want to run a bash (using docker exec ... ) in detach mode and then attach (using docker attach ... ) to it later.
As you know we can run new process inside a container, e.g:
docker exec -itd my_container bash
By this way a new bash process will run inside this container.
Now my question is that how to attach to this process later?
I tried to run following command but it just shows the nginx live log:
docker attach my_nginx2
If I understand your use case, you can do this :
docker run -itd --name=my_container nginx:latest bash -i -c 'nginx; bash -i'
this allows you to do :
docker attach my_container
you can detach from a container and leave it running using the CTRL-p CTRL-q key sequence.
I am trying to deploy db2 express image to docker using non-root user.
The below code is used to start the db2engine using root user, it works fine.
FROM ibmoms/db2express-c:10.5.0.5-3.10.0
ENV LICENSE=accept \
DB2INST1_PASSWORD=password
RUN su - db2inst1 -c "db2start"
CMD ["db2start"]
The below code is used to start the db2engine from db2inst1 profile, giving below exception during image build. please help to resolve this.( I am trying to avoid su - command )
FROM ibmoms/db2express-c:10.5.0.5-3.10.0
ENV LICENSE=accept \
DB2INST1_PASSWORD=password
USER db2inst1
RUN /bin/bash -c ~db2inst1/sqllib/adm/db2start
CMD ["db2start"]
SQL1641N The db2start command failed because one or more DB2 database manager program files was prevented from executing with root privileges by file system mount settings.
Can you show us your Dockerfile please?
It's worth noting that a Dockerfile is used to build an image. You can execute commands while building, but once an image is published, running processses are not maintained in the image definition.
This is the reason that the CMD directive exists, so that you can tell the container which process to start and encapsulate.
If you're using the pre-existing db2 image from IBM on DockerHub (docker pull ibmcom/db2), then you will not need to start the process yourself.
Their quickstart guide demonstrates this with the following example command:
docker run -itd --name mydb2 --privileged=true -p 50000:50000 -e LICENSE=accept -e DB2INST1_PASSWORD=<choose an instance password> -e DBNAME=testdb -v <db storage dir>:/database ibmcom/db2
As you can see, you only specify the image, and leave the default ENTRYPOINT and CMD, resulting in the DB starting.
Their recommendation for building your own container on top of theirs (FROM) is to load all custom scripts into /var/custom, and they will be executed automatically after the main process has started.
I have a strange issue. I have configured a SSH_USER on Jenkins and trying to deploy a simple docker-service with "deploy-over-SSH".
Every time I deploy it Exits as below, and logs just says "Terminated"
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bea48e1ee755 localhost/my-image:latest /bin/sh -c npm ru... 13 seconds ago Exited (143) 13 seconds ago 0.0.0.0:6007->3000/tcp my-cont
$ docker logs my-cont
Terminated
But if I try running manually on the same server with same SSH_USER, I am able to run docker container successfully.
docker run -d -it -p 6007:3000 --name my-cont my-image
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
nce48e1ee721 localhost/my-image:latest /bin/sh -c npm ru... 21 minutes ago 21 minutes ago 0.0.0.0:6007->3000/tcp my-cont
The script I am running over-SSH is very simple from Jenkins, I am passing the Port from Jenkins,
$ bash ./run.sh $Port
docker run -d -it -p $1:3000 --name my-cont my-image
Not sure , what is causing the issue.
As I mentioned in the comment, upgrading the version 'podman version 2.0.5' worked for me.
The error or docker logs never gave me any hint, clue on version.
But that was the solution. Thanks for your comments.
I have a very simple dockerfile with only one row, namely "FROM ubuntu". I created an image from this dockerfile by the command docker build -t ubuntu_ .
I know that I can create a new docker container from this image an run it interactively with the command
docker run -it my_new_container
I can later start this new container with the command
start my_new container
As I understand it, I should also be able to use this container it interactively by
start -i my_new container
But, it does not work. It just runs and exits. I don't get to the container's command prompt as I do when I use run. What am I doing wrong?
If i understood correctly, you want to see the logs from container in terminal, same as when you run the image with docker run. If that's the case, then try with
docker start -a my_docker_container
You can enter a running container with:
docker exec -it <container name> /bin/bash
example:
docker exec -it my_new_container /bin/bash
you can replace bash with sh if bash is not available in the container.
and if you need to explicitly use a UID , like root = UID 0, you can specify this:
docker exec -it -u 0 my_new_container /bin/bash
which will log you as root
Direct answer:
To run an interactive shell for a non-running container, first find the image that the container is based on.
Then:
docker container run -it [yourImage] bash
If your eventual container is based on an alpine image, replace bash with sh.
Technically, this will create a NEW container, but it gets the job done.
EDIT [preferred method]:
An even better way is to give the container something irrelevant to do. A nice solution from the VSCode docs is to put the following command into your service definition of the docker-compose.yml file:
services:
my-app-service:
command: ["sleep", "infinity"]
# other relevant parts of your service def...
The idea here is that you're telling your container to sleep for some time (infinite amount of time). Ironically, this your container will have to maintain this state, forcing the container to keep running.
This is how I run containers. Best wishes to whomever needs this nugget of info. We're all learning :)
You cannot get a shell into a container in its stopped state, or restart it directly with another entry point. If the container keeps exiting and you need to examine it, the only option I know of is to commit the container as a new image and then start a new container with such image, as per a related answer.
If you don't need that container anymore and just want it to stay up, you should run it with a process that will not exit. An example with an Ubuntu image would be (you don't need a Dockerfile for this):
docker run -d ubuntu --name carrot tail -f /dev/null
You will see that this container stays up and you can now run bash on it, to access the CLI:
docker exec -ti carrot bash
If the container has stopped for whatever reason, such as a machine restart, you can bring it back up:
docker start carrot
And it will continue to stay up again.
I have a docker image (MyBaseImage) where I have Open SSH server installed. Now in the docker file, I have the following.
#Download base image
FROM MyBaseImage
RUN service ssh start
I build the new image by typing
docker build .
Docker builds the image fine, giving the following information.
Step 1/2 : FROM MyBaseImage
---> 56f88e347f77
Step 2/2 : RUN service ssh start
---> Running in a1afe0c2ce71
* Starting OpenBSD Secure Shell server sshd [ OK ]
Removing intermediate container a1afe0c2ce71
---> 7879cebe8b6a
But when I run the new image by typing
docker run -it 7879cebe8b6a
Typing the following in the terminal of the container
service ssh status
gives
* sshd is not running
I have to then manually start the Open SSH server by typing service ssh start.
What could be the reason for it?
If you look at your build, you can see the ssh service start in an intermediate container which is deleted in the next build step:
---> Running in a1afe0c2ce71
* Starting OpenBSD Secure Shell server sshd [ OK ]
Removing intermediate container a1afe0c2ce71
To start a service in a Dockerfile, you should use either a CMD or ENTRYPOINT statement as the last line (depending on whether you might want to pass an argument in the docker run ... command, normally.
Generally, a service will start in the background as a daemon however, so having this as your last line:
CMD ["service", "ssh", "start"]
Will not work, as the container will exit as it has nothing do to
What you probably want (from the docker docs) is this:
CMD ["/usr/sbin/sshd", "-D"]
Which starts the service in the foreground so that the container will stay alive
This link has useful info about the difference between CMD & ENTRYPOINT, and also the difference between the exec & shell formats.
Depending on which distro of linux you are using command slightly changes.
If you are using ubuntu your start command should work.
But if your base image is centos/RHEL try service sshd start