I'd like to learn the Dockerfile from a very simple start, so here's my Dockfile:
FROM ubuntu
ENTRYPOINT /bin/bash
however, after building the image and run the container, I find that I can't run the bash commands. For example, if I type:
# clear
The container seems to get stuck running in an infinite loop.
So why does that happen? How can I fix it?
How are you running the container? Note that you have to pass the options -i in order to keep STDIN open and the -t to allocate a pseudo-TTY.
Below you can find an example:
docker run -i -t my-image
docker run -it ubuntu
Post this command, you will have a prompt like:
root#26f9e7a42517:/#
Related
I present to you the following dilemma I execute my script manually and it works well, see next line for example:
docker exec -ti backup_subversion sh -c "/tmp/my_script.sh"
But when I attempt to schedule the process this line is just skipped.
I have tried to execute just a touch command and it too is ignored.
I have tried to execute as root, same problem.
I have tried to execute in another docker environment: same problem.
My OS is Centos 7.
In this script for example the bug part who will crash :
#!/bin/bash
# Create a container.
docker run -d --name=backup_subversion \
-v /subversion/dump:/var/dump \
--net my_network my_server.domaine.com/subversion/billy:1.9
# I copy a script.
docker cp tools_subversion_dump.sh backup_subversion:/tmp
# This line is ignore since crontab exec.
docker exec -ti backup_subversion sh -c "/tmp/tools_subversion_dump.sh"
Thank you in advance for your answers because it's a mystery to me.
It's probably because you used the -it options that only apply to an interactive shell rather then a pseudo one like the one used in scripts as referenced in the question
I have a simple Dockerfile that copies over a template which I used sed to replace some of the variables. Pretty straight forward. Looks very doable and from what I've seen/read for all intents and purposes, it should do it.
COPY /my-dir/my-textfile.conf /to/my/docker/path.conf
RUN sed -i s:TEXTTOREPLACE:my-new-text:g /to/my/docker/path.conf
I then run docker build.... then docker run ... bash
then I cat my file and TEXTTOREPLACE is still there.
Run the same sed command in the bash and it works no problem.
Any thoughts? What am I doing wrong/not seeing?
Thanks!
EDIT per request: base image is debian:7.11, work station is MAC OSX
Just to recap.
I have the file my-textfile.conf in my working directory. Its content is:
I need to change TEXTTOREPLACE with my-new-text
My test system is Ubuntu Linux 16.04 running Docker version 18.09.0, build
4d60db4.
This is the Dockerfile
FROM debian:7.11
COPY my-textfile.conf /tmp/path.conf
RUN sed -i s:TEXTTOREPLACE:my-new-text:g /tmp/path.conf
I run the following commands:
docker build -t mytestimage .
docker run -ti -d --name mytestcontainer mytestimage
docker exec -ti mytestcontainer /bin/bash
Then, inside the container, I run:
cat /tmp/path.conf
and I get this result:
I need to change my-new-text with my-new-text
So it seems it works as expected.
After trying to test Dockerfiles with Dockerspec, I finally had an issue I can't resolve properly.
The problem is, I think, from Docker itself ; If I understand its process, an Entrypoint is only executed at run, but if the container stay started and I launch an "exec" command in, it's not re-called.
I think it's the wanted behavior.
But if the Entrypoint is a "gosu" script which precede all my commands, it's a problem...
Example
"myImage" has this Entrypoint :
gosu 1000:1000 "$#"
If I launch : docker run -it myImage id -u
The output is "1000".
If I start a container : docker run -it myImage bash
In this container, id -u outputs "1000".
But if I start a new command in this container, it starts a new shell, and does not execute the Entrypoint, so : docker exec CONTAINER_ID id -u
Output "0", because the new shell is started as "root".
It there a way to execute each time the entrypoint ?
Or re-use the shell open ?
Or a better way to do that ?
Or, maybe I haven't understand anything ? ;)
Thanks !
EDIT
After reading solutions proposed here, I understand that the problem is not how Docker works but how Serverspec works with ; my goal is to directly test a command as a docker run argument, but Serverspec start a container and test commands with docker exec.
So, the best solution is to found how get the stdout of the docker run executed by Serverspec.
But, in my personal use-case, the best solution is maybe to not use Gosu but --user flag :)
if your goal is to run the docker exec with a specific user inside of the container, you can use the --user option.
docker exec --user myuser container-name [... your command here]
If you want to run gosu every time, you can specify that as the command with docker exec
docke exec container-name gosu 1000:1000 [your actual command here]
in my experience, the best way to encapsulate this into something easily re-usable is with a .sh script (or .cmd file in windows).
drop this into a file in your local folder... maybe gs for example.
#! /bin/sh
docker exec container-name gosu 1000:1000 "$#"
give it execute permissions with chmod +x gs and then run it with ./gs from the local folder
I am trying to create a shell script for setting up a docker container. My script file looks like:
#!bin/bash
docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash
Running this script file will run the container in a newly invoked bash.
Now I need to run a script file (test.sh)which is already inside container from the above given shell script.(eg: cd /path/to/test.sh && ./test.sh)
How to do that?
You can run a command in a running container using docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:
docker exec mycontainer /path/to/test.sh
And to run from a bash session:
docker exec -it mycontainer /bin/bash
From there you can run your script.
Assuming that your docker container is up and running, you can run commands as:
docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"
I was searching an answer for this same question and found ENTRYPOINT in Dockerfile solution for me.
Dockerfile
...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash
Now the scripts are executed when I start the container and I get the bash prompt after the scripts has been executed.
In case you don't want (or have) a running container, you can call your script directly with the run command.
Remove the iterative tty -i -t arguments and use this:
$ docker run ubuntu:bionic /bin/bash /path/to/script.sh
This will (didn't test) also work for other scripts:
$ docker run ubuntu:bionic /usr/bin/python /path/to/script.py
This command worked for me
cat local_file.sh | docker exec -i container_name bash
You could also mount a local directory into your docker image and source the script in your .bashrc. Don't forget the script has to consist of functions unless you want it to execute on every new shell. (This is outdated see the update notice.)
I'm using this solution to be able to update the script outside of the docker instance. This way I don't have to rerun the image if changes occur, I just open a new shell. (Got rid of reopening a shell - see the update notice)
Here is how you bind your current directory:
docker run -it -v $PWD:/scripts $my_docker_build /bin/bash
Now your current directory is bound to /scripts of your docker instance.
(Outdated)
To save your .bashrc changes commit your working image with this command:
docker commit $container_id $my_docker_build
Update
To solve the issue to open up a new shell for every change I now do the following:
In the dockerfile itself I add RUN echo "/scripts/bashrc" > /root/.bashrc". Inside zshrc I export the scripts directory to the path. The scripts directory now contains multiple files instead of one. Now I can directly call all scripts without having open a sub shell on every change.
BTW you can define the history file outside of your container too. This way it's not necessary to commit on a bash change anymore.
Thomio's answer is helpful but it expects the script to exist inside the image. If you have a one-of script that you want to run/test inside a container (from command-line or to be useful in a script), then you can use
$ docker run ubuntu:bionic /bin/bash -c '
echo "Hello there"
echo "this could be a long script"
'
Have a look at entry points too. You will be able to use multiple CMD
https://docs.docker.com/engine/reference/builder/#/entrypoint
If you want to run the same command on multiple instances you can do this :
for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
This is old, and I don't have enough reputation points to comment. Still, I guess it is worth sharing how one can generalize Marvin's idea to allow parameters.
docker exec -i mycontainer bash -s arg1 arg2 arg3 < mylocal.sh
I want to ssh or bash into runned docker container. Please, see example:
$ sudo docker run -d webserver
webserver is clean image from ubuntu:14.04
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
665b4a1e17b6 webserver:latest /bin/bash ... ... 22/tcp, 80/tcp loving_heisenberg
now I want to get something like this (go into runned container):
$ sudo docker run -t -i webserver (or maybe 665b4a1e17b6 instead)
$ root#665b4a1e17b6:/#
Previously I used Vagrant so I want to get behavior similar to vagrant ssh. Please, could anyone help me?
After the release of Docker version 1.3, the correct way to get a shell or other process on a running container is using the docker exec command. For example, you would run the following to get a shell on a running container:
docker exec -it myContainer /bin/bash
You can find more information in the documentation.
The answer is docker attach command.
For information see: https://askubuntu.com/a/507009/159189