Docker: Running nano in docker container - docker

I open an interactive shell into a docker container like so
sudo docker exec -t -i {container_name} bash
So far so good but trying to run nano results in:
Error opening terminal: unknown.

I think this can be related with Docker Issue #9299.
There are some workarounds commented in that issue:
Run the container allocating a pseudo-TTY (option -t).
Export environment variable $TERM=xterm in the container's process run in exec (i.e.: export TERM=xterm)

Run comand : export TERM=xterm

You can add
ENV TERM xterm
to your Dockerfile if you will use the editor regularly. We have that setting in our base container, since we're constantly debugging things with vi/emacs.

docker exec -it id_container bash
apt-get update
apt-get install nano
export TERM=xterm

as $TERM was already set to xterm but still not working for me, here is a way that worked: docker exec -it [CONTAINER_ID] /bin/bash -c "export TERM=xterm; exec bash"

Run this command in your container apk add nano

I did a workaround, in my .bashrc i have added:
alias nano='export TERM=xterm && nano'
In this case the error no longer appear

For me export TERM=xterm causes some display issues described here:
https://superuser.com/questions/1172222/issues-editing-files-with-nano-in-bash-windows-10
In that case export TERM=linux may works better.

I don't know if we are talking about the same thing but you need to make apt update | apt install nano so you can install it in the container.

Related

How to navigate to different folder in prebuilt Docker container?

I'm using a prebuilt container from Dockerhub. When I run the container it acts like it's in a folder called workspace, since my run command sudo docker run -it shubhamgoel/birds:bigbang bash returns root#eg2e775g0a1b:/workspace#
I don't know how to navigate to the correct folder. I need to run this container in a folder /home/s/ucmr.
If I do
sudo docker run -it shubhamgoel/birds:bigbang bash -c "cd:/home/s/ucmr"
I get
bash: cd:/home/s/ucmr: No such file or directory
How do I navigate to the correct folder with this prebuilt container? Thank you.
__
Edit: I've tried
sudo docker run -v /kitty:/dog --name kittycat -it shubhamgoel/birds:bigbang
and when I search for 'dog' on my disk there's no such folder. Also when I type in mkdir frog and search for 'frog' on my disk there's no such folder...
docker run -it shubhamgoel/birds:bigbang bash -c "cd:/home/s/ucmr" is wrong for 2 reasons. The first one has already been covered by the other answer (wrong syntax with cd command). The other is that using the -it docker option with a non-interactive bash is kind of meaningless. The -c bash option just means "execute whatever there is between the double quotes and return to the caller", this last part makes the interactivity vanish.
A first naive solution, but still working, could be creating another shell like this:
docker run -it shubhamgoel/birds:bigbang bash -c "cd /home/s/ucmr && bash"
However, docker is far smarter and flexible and lets you override some Dockerfile directive, for instance the WORKDIR:
docker run -it -w="/home/s/ucmr" shubhamgoel/birds:bigbang bash

Using docker with running process

I've created this docker file which works for
FROM debian:9
ENV CF_CLI_VERSION "6.21.1"
# Install prerequisites
RUN ln -s /lib/ /lib64
RUN apt-get update && apt-get install curl -y
RUN curl -L "https://cli.run.pivotal.io/stable?release=linux64-binary&version=${CF_CLI_VERSION}" | tar -zx -C /usr/local/bin
And it works as expected, now I run it like following
docker run -i -t cf-cli cf -v
and I see the version
Now every command which I want to run is something like
docker run -i -t cf-cli cf -something
my question is how can I enter into container and do ls etc without every-time doing
docker run -i -t cf-cli ...
I want to enter to the container like you enter to machine.
Step 1:
Run the container in background:
docke run -d --name myapp dockerimage
Step2:
Exec into the containr myapp:
docker exec -it myapp bash
run any commands inside as u wish
Have a look at docker exec. You'll probably want something like docker exec -it containername bash depending on the shell installed in the container.
If I correcly understand you just need
docker exec -it <runningcontainername> bash

Error "The input device is not a TTY"

I am running the following command from my Jenkinsfile. However, I get the error "The input device is not a TTY".
docker run -v $PWD:/foobar -it cloudfoundry/cflinuxfs2 /foobar/script.sh
Is there a way to run the script from the Jenkinsfile without doing interactive mode?
I basically have a file called script.sh that I would like to run inside the Docker container.
Remove the -it from your cli to make it non interactive and remove the TTY. If you don't need either, e.g. running your command inside of a Jenkins or cron script, you should do this.
Or you can change it to -i if you have input piped into the docker command that doesn't come from a TTY. If you have something like xyz | docker ... or docker ... <input in your command line, do this.
Or you can change it to -t if you want TTY support but don't have it available on the input device. Do this for apps that check for a TTY to enable color formatting of the output in your logs, or for when you later attach to the container with a proper terminal.
Or if you need an interactive terminal and aren't running in a terminal on Linux or MacOS, use a different command line interface. PowerShell is reported to include this support on Windows.
What is a TTY? It's a terminal interface that supports escape sequences, moving the cursor around, etc, that comes from the old days of dumb terminals attached to mainframes. Today it is provided by the Linux command terminals and ssh interfaces. See the wikipedia article for more details.
To see the difference of running a container with and without a TTY, run a container without one: docker run --rm -i ubuntu bash. From inside that container, install vim with apt-get update; apt-get install vim. Note the lack of a prompt. When running vim against a file, try to move the cursor around within the file.
For docker run DON'T USE -it flag
(as said BMitch)
And it's not exactly what you are asking, but would be also useful for others:
For docker-compose exec use -T flag!
The -T key would help people who are using docker-compose exec! (It disable pseudo-tty allocation)
For example:
docker-compose -f /srv/backend_bigdata/local.yml exec -T postgres backup
or
docker-compose exec -T mysql mysql -uuser_name -ppassword database_name < dir/to/db_backup.sql
For those who struggle with this error and git bash on Windows, just use PowerShell where -it works perfectly.
If you are using git bash on windows, you just need to put
winpty
before your 'docker line' :
winpty docker exec -it some_container bash
In order for docker to allocate a TTY (the -t option) you already need to be in a TTY when docker run is called. Jenkins executes its jobs not in a TTY.
Having said that, the script you are running within Jenkins you may also want to run locally. In that case it can be really convenient to have a TTY allocated so you can send signals like ctrl+c when running it locally.
To fix this make your script optionally use the -t option, like so:
test -t 1 && USE_TTY="-t"
docker run ${USE_TTY} ...
when using 'git bash',
1) I execute the command:
docker exec -it 726fe4999627 /bin/bash
I have the error:
the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'
2) then, I execute the command:
winpty docker exec -it 726fe4999627 /bin/bash
I have another error:
OCI runtime exec failed: exec failed: container_linux.go:344: starting container process caused "exec: \"D:/Git/usr/bin/
bash.exe\": stat D:/Git/usr/bin/bash.exe: no such file or directory": unknown
3) third, I execute the:
winpty docker exec -it 726fe4999627 bash
it worked.
when I using 'powershell', all worked well.
Using docker-compose exec -T fixed the problem for me via Jenkins
docker-compose exec -T containerName php script.php
Same Case Here, I am running the following command throw .sh script(bash) and python .py
However, I get the same error "The input device is not a TTY".
in my case, I'm trying to take the dump from a running container of my "production" env with authentication and passing with some arguments,
then take the output of .bak file of my mssql database container.
Remove -it from the command. If you want to keep it interactive then keep -i.
you can check my .sh file and a long command taking dump.
if using windows, try with cmd , for me it works. check if docker is started.
My Jenkins pipeline step shown below failed with the same error.
steps {
echo 'Building ...'
sh 'sh ./Tools/build.sh'
}
In my "build.sh" script file "docker run" command output this error when it was executed by Jenkins job. However it was working OK when the script ran in the shell terminal.The error happened because of -t option passed to docker run command that as I know tries to allocate terminal and fails if there is no terminal to allocate.
In my case I have changed the script to pass -t option only if a terminal could be detected. Here is the code after changes :
DOCKER_RUN_OPTIONS="-i --rm"
# Only allocate tty if we detect one
if [ -t 0 ] && [ -t 1 ]; then
DOCKER_RUN_OPTIONS="$DOCKER_RUN_OPTIONS -t"
fi
docker run $DOCKER_RUN_OPTIONS --name my-container-name my-image-tag
I know this is not directly answering the question at hand but for anyone that comes upon this question who is using WSL running Docker for windows and cmder or conemu.
The trick is not to use Docker which is installed on windows at /mnt/c/Program Files/Docker/Docker/resources/bin/docker.exe but rather to install the ubuntu/linux Docker. It's worth pointing out that you can't run Docker itself from within WSL but you can connect to Docker for windows from the linux Docker client.
Install Docker on Linux
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce
Connect to Docker for windows on the port 2375 which needs to be enabled from the settings in docker for windows.
docker -H localhost:2375 run -it -v /mnt/c/code:/var/app -w "/var/app" centos:7
Or set the docker_host variable which will allow you to omit the -H switch
export DOCKER_HOST=tcp://localhost:2375
You should now be able to connect interactively with a tty terminal session.
In Jenkins, I'm using docker-compose exec -T
eg:-
docker-compose exec -T app php artisan migrate
winpty works as long as you don't specify volumes to be mounted such as .:/mountpoint or ${pwd}:/mountpoint
The best workaround I have found is to use the git-bash plugin inside Visual Code Studio and use the terminal to start and stop containers or docker-compose.
For those using Pyinvoke see this documentation which I'll syndicate here in case the link dies:
99% of the time, adding pty=True to your run call will make things work as you were expecting. Read on for why this is (and why pty=True is not the default).
Command-line programs often change behavior depending on whether a controlling terminal is present; a common example is the use or disuse of colored output. When the recipient of your output is a human at a terminal, you may want to use color, tailor line length to match terminal width, etc.
Conversely, when your output is being sent to another program (shell pipe, CI server, file, etc) color escape codes and other terminal-specific behaviors can result in unwanted garbage.
Invoke’s use cases span both of the above - sometimes you only want data displayed directly, sometimes you only want to capture it as a string; often you want both. Because of this, there is no “correct” default behavior re: use of a pseudo-terminal - some large chunk of use cases will be inconvenienced either way.
For use cases which don’t care, direct invocation without a pseudo-terminal is faster & cleaner, so it is the default.
Instead of using -it use --tty
So your docker run should look like this:
docker run -v $PWD:/foobar --tty cloudfoundry/cflinuxfs2 /foobar/script.sh
use only -i flag than -it flag. which can help you to see what going on inside container.
docker exec -i $USER bash <<EOF
apt install nano -y
EOF
you might see the warning but it shows you output on the terminal inside docker.

Why is it not possible to call locale-gen with sudo inside a docker container?

$ sudo docker run -it --rm --privileged=true debian-jessie su - dib -c /bin/bash
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
dib#4a199f1d95f9:~$ sudo locale-gen
Generating locales (this might take a while)...
en_US.UTF-8... done
$
At this point the docker container exists (not running any longer).
On the other hand, when using:
$ sudo docker run -it --rm --privileged=true debian-jessie /bin/bash
root#55e8d2ab53f1:/# locale-gen
Generating locales (this might take a while)...
en_US.UTF-8... done
Generation complete.
root#55e8d2ab53f1:/#
locale-gen runs fine without problems and the docker container continues to run.
Can somebody please explain, why the locale-gen runs fine in the second example but not in the first?
Are there any solutions or workarounds running locale-gen with sudo?
Technical background: the docker images were generated with diskimage-builder from OpenStack. I tested this with three images: debian-jessie, debian-stretch and ubuntu-trusty - all gave the same results.
For the files:
Did not find the root cause - but a workaround: starting the docker with runuser instead of su solved the problem for me:
sudo docker run -it --rm --privileged=true debian-jessie runuser -l dib -c /bin/bash

Changing the default command of base docker images

I downloaded the ubuntu base image from the docker hub. Now I am trying to build a new image based on the ubuntu image. However, I want the default command for the ubuntu image to be "/bin/bash -c" instead of "/bin/sh" so as when I use RUN in my Dockerfile, it accesses bash instead of sh. Notice I am talking about the default command of the same image, not the image I am trying to build.
maybe this can help:
SHELL ["/bin/bash", "-c"]
Reference:
https://github.com/moby/moby/issues/7281#issuecomment-389440503
I don't think there is a default command in the ubuntu image. When you run
$ docker run ubuntu echo hi
hi
it runs ["/bin/echo", "hi"]. You can verify that by running
$ docker run ubuntu set
2014/06/20 08:38:54 exec: "set": executable file not found in $PATH
set is built-in command in shell, but docker tries to run it as an external one.
If you want to change the default shell from dash to bash, you can create an image with the fixed symlink. Here's a dockerfile:
FROM ubuntu
RUN ln -sf /bin/bash /bin/sh
[EDIT]
I just realized what you're talking about. I don't know if you can change the default for RUN command, but you can explicitly use /bin/bash like this:
RUN /bin/bash -c ...
You can use:
RUN ["/bin/bash", "-c", "<command>"]

Resources