What is the difference between running docker exec in terminal and in bash script - bash

Let's assume I run the following command inside a script:
#!/usr/bin/env bash
docker run --name mydb --rm -e POSTGRES_PASSWORD=kgalli -e POSTGRES_USER=kgalli -p "9999:5432" -v $PWD/db:/opt -d postgres
When I then run the following command to create a database it works fine.
docker exec -e PGPASSWORD=kgalli mydb psql -U kgalli -d template1 -c "CREATE DATABASE kgalli_test WITH OWNER kgalli ENCODING 'UTF8' LC_COLLATE = 'en_US.utf8' LC_CTYPE = 'en_US.utf8';"
However when I add this line to the script above, so the script not only starts the postgres server but also creates the database it fails.
I do not really understand why I get the following error:
psql: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
I know I can instruct docker postgres image to create a database on start. But this is actually not what I want to achieve. I just using this as an example to understand the problem.

When you're running it in a script, it's most likely just happening too quickly. The docker run … command returns immediately, and then docker exec … is attempting to use PostgreSQL while the database server is still starting up. You need to wait for it to be ready before creating the extra database.
That said, the postgres image has functionality in its entrypoint script to run custom initialization scripts. You can put your CREATE DATABASE … statement into a .sql file or config and mount it into /docker-entrypoint-initdb.d in the container. The postgres container will automatically run it when the database server is ready.
The docs for this seems to have disappeared, but you can see the implementation in docker-entrypoint.sh.

Using docker run, you are starting a new container, using docker exec, you are executing a command in already running container

The docker run command first creates a writeable container layer over the specified image, and then starts it using the specified command.
The docker exec command runs a new command in a running container.
If the container is paused, then the docker exec command will fail with an error
$ docker pause test
test
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1ae3b36715d2 ubuntu:latest "bash" 17 seconds ago Up 16 seconds (Paused) test
$ docker exec test ls
FATA[0000] Error response from daemon: Container test is paused, unpause the container before exec
$ echo $?
1
(ref.1)
(ref.2)

Related

Exit from docker exec -ti in shell script

I'm writing a script where I execute the following command:
docker exec -ti keycloak11_service-keycloak_1 /opt/jboss/keycloak/bin/standalone.sh \
-Djboss.socket.binding.port-offset=151 \
-Dkeycloak.migration.action=export \
-Dkeycloak.migration.provider=singleFile \
-Dkeycloak.migration.realmName=demo \
-Dkeycloak.migration.usersExportStrategy=REALM_FILE \
-Dkeycloak.migration.file=/keycloak/realm-export.json
This exports the file realm-export.json from my running keycloak instance. After the execution I want to to do a scp to another server. The problem is, when I execute the ti comment, the standalone keycloak is started and my script stucks while it says : Listening in port ...
As the export operation is finished at that point, I could kill the process or enter any command (which is cmd+c). Is there a way to do this via script?
Put your commands in a Dockerfile and run the container in detached mode docker run -d. Also you could use a bind-mount to access a host volume from the container. That way your results are stored on the host and you can access them later.

Docker container exits as soon as I start it

When I run or start a Docker container, it will not stay running.
Docker start will just return the name of whatever container I gave it, but wont actually do anything. Docker run (ex $ docker run -p 8080:80 --name hello -d hello-world) will create it but it will exit immediately.
If I run docker ps after one of these, it will show nothing listed as currently running.
If I run docker ps -a, it will show all of my containers and show the one that I just attempted to run having exited a few seconds ago.
Is this common and how do I get my containers to stay running? I am trying to learn how to use Docker and it has been one of the worst experiences. Thank you for any help or suggestions
Docker containers are generally used to run applications/processes in an isolated environment.
When you run the hello-world image, it creates a container which has only purpose of printing out the name using standard output. That is the only process that ran and the container was done with its work. That is why you see nothing when done docker ps.
In order to keep a container running, you need to have a process inside that container that will run (for example: a server, database, application etc.)
Try creating a container form mysql image, and then check the running container.
In your command, you specify the -d flag (aka detach), which means Run container in background and print container ID (from Docker docs). See more discussion about this here: Docker container will automatically stop after "docker run -d"
docker run -p 8080:80 --name hello -d hello-world
If you run it without the -d flag, it should run in the foreground and send output to your terminal
docker run -p 8080:80 --name hello hello-world
You don't see it running in docker ps -a because that container just executes the hello-world script and exits. If the container starts a long running process then you'll be able to find it in docker ps -a. To verify this, you can try running the nginx demo containers (e.g. nginx-hello) which serve up 'hello world'/demo pages.
To know what's wrong with your container use (docker logs (your container name)) command.
then you can sort it out what went wrong with your container
Is this common and how do I get my containers to stay running?
What happen when you start a Docker container ?
By default, it executes the command/the entrypoint specified in the Dockerfile image.
Generally that command or the entrypoint is a script or a program located in the image.
When that script/program exits, the container exits too. That's all.
To keep a container alive, the script/program has to stay running.
You start an hello image container, a "hello" container says "hello" and exits.
That may be a script as simple as :
#!/bin/sh
echo "hello"
So that is expected to finish and exit the container.
Run a database or a web server and you will see a different behavior. The script/program keeps running... while you don't stop that. So the container also stays running while you don't stop that.
To experiment, you can run your hello-world container with an endless command :
docker run -p 8080:80 --name hello -d hello-world --entrypoint tail -f /dev/null
You will see that the container stays running.
A docker container exits when its main process finishes. The hello-world main process just prints some text and exits, so container exits too.
You can run this command straightly to see it's text:
docker run hello-world
If you want a running container, maybe you can try a nginx demo:
docker run --name nginx-demo -p 8080:80 -d nginx
then you can visit http://localhost:8080 using your web browser.

Docker exec -it <containerid> dir doesn't work. Why? How to get directory info?

I'm very new to docker.
Also I'm using Docker for Windows (ie Image and Container are for Windows OS).
I'm trying to get a list of all the folders and subfolders to resolve another issue I'm having. I read several post and blogs and seems like I should be able to run
docker exec -it <container id> dir
To get the info as it is suppose to allow me to run commands against the container.
I even ran
docker exec -it f83eb1533b67 help
which gave me a list of commands (because no one tells what are acceptable 'commands'...) and it is listed. however I get the following message when I run DIR command
PS P:\docker\tmp\SqlServerSetup> `docker exec -it f83eb1533b67 dir`
container f83eb1533b671b4462b8a1562da7343185b2dd27e94ff360e0230969d432ec37 encountered an error during CreateProcess: failure in a Windows system call: The system cannot find the file specified. (0x2)
[Event Detail: Provider: 00000000-0000-0000-0000-000000000000] extra info: {"CommandLine":"dir","WorkingDirectory":"C:\\","Environment":{"ACCEPT_EULA":"Y","attach_dbs":"[]","sa_password":"Pass1.4DBAs","sa_password_path":"C:\\ProgramData\\Docker\\secrets\\sa-password"},"EmulateConsole":true,"CreateStdInPipe":true,"CreateStdOutPipe":true,"ConsoleSize":[0,0]}
PS P:\docker\tmp\SqlServerSetup>
Please note: I don't want to persist a volume. Seems like that option is for people that are trying to reuse data.
UPDATE:
This is the statement that i'm using to create the container:
docker run -p 1433:1433 -e sa_password=Pass1.4DBAs -e ACCEPT_EULA=Y -p 11433:1433 --name sqlTraining --cap-add SYS_PTRACE -d microsoft/mssql-server-windows-developer
It works fine. Container is created, but I want to view the filesystem within that container.
For Windows containers, prefix the command with the command shell (cmd) and the /c parameter. For example:
docker exec <container id> cmd /c dir
This will execute the dir command on the specified container and terminate.
Try running:
docker exec -it <container id> sh
to start the interactive shell console. This should help you with debugging.

Running shell script using Docker image

Input:
- There is Windows machine with Docker Toolbox installed.
- There is a shell script file baz.sh which calls py2dsc-deb.
Problem: py2dsc-deb is not available on Windows.
As I understand correctly, I can pull some Linux distro image from Docker repository, create a container and then execute shell-script file and it will run py2dsc-deb and do its job.
I have pulled:
debian - stretch-slim - 3ad21 - 3 weeks ago - 55.3MB
Now
How do I run my script using debian, something like: docker exec mycontainer /path/to/test.sh?
Running docker --rm debian:stretch-slim does nothing. Doesn't it suppose to run Debian distro at docker-machine ip?
I have tried to keep the container up using docker run -it debian:stretch-slim /bin/bash, then run the script using docker exec 1ef5b ./build.sh, but getting
$ docker exec 745 ./build.sh
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"./build.sh\": stat ./build.sh: no such file or directory"
Does it mean I can't run external script and has to always pass it inside the Docker?
You can execute bash command inside your container by typing
docker exec -ti -u `username` `container_name` bash -c "cd /path/to/ && ./test.sh"
lets say your container name is test_buildbox, you are root and your script stays inside /bin/test.sh You can call this script by typing
docker exec -ti -u root test_buildbox bash -c "cd /bin/ && ./test.sh
Please check if you have correct line endings in your .sh scripts (<LF>) when you built Docker image on Windows.

DockerFile : how to get bash command line after start?

This question is not duplicated, because I want to obtain an interactive shell without running with -it flags.
I'm moving first steps into Docker to create images only for internal use.
I start from this envirornment_full.df:
FROM ubuntu:16.04
ENTRYPOINT ["/bin/bash"]
I then build
docker rmi environment:full
docker build -t environment:full -f environment.df .
Then run
docker run environment:full
Running docker images -am I see my image
REPOSITORY TAG IMAGE ID CREATED SIZE
environment full aa91bbd39167 4 seconds ago 129 MB
So I run it
docker run environment:full
I see nothing happening ....
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5847c0a18f30 environment:full "/bin/bash" 21 seconds ago Exited (0) 20 seconds ago admiring_mirzakhani
Also
$ docker run environment:full -ti
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
root#aa768a585f33:/# exit
I'd like to have the ubuntu prompt, like if I was in a SSH connection. And this without user must enter -i or -tty flags.
How can I realize this?
bash won't run at all if stdin is closed. If you don't provide the -i flag, bash will simply exit immediately. So when you...
docker run environment:full
...bash exits immediately, and so your container exits. You would see it if you ran docker ps -a, which shows container that have stopped.
bash won't give you an interactive prompt if it's not attached to a tty. So if you were to run...
coerk run -i environment:full
...you would get a bash shell, but with no prompt, or job control, or other features. You need to provide -t for Docker to allocate a tty device.
You can't get what you want without providing both the -i and -t options on the command line.
An alternative would be to set up an image that runs an ssh daemon, and have people ssh into the container. Instead of behaving "like if I was in a SSH connection", it would actually be an ssh session.
Also, note that this:
docker run environment:full -ti
Is not the same as this:
docker run -it environment:full
The former will run bash -ti inside a container, while the latter passes the -i and -t options to docker run.

Resources