Docker commiting changes overrides default start command - docker

I have a jupyter notebook docker image from https://hub.docker.com/r/jupyter/datascience-notebook/.
Typically I run the notebook using this command
docker run -it --rm -p 8888:8888 -v /home/folder/Projects/:/home/jovyan/Projects -e NB_UID=1000 jupyter/datascience-notebook
This works perfectly and I am presented with the message that notebook is running. I am able to create notebooks, run them etc.
Now I want to install the jupyter contrib extenstions from https://github.com/ipython-contrib/jupyter_contrib_nbextensions. I followed the instructions here at: https://gist.github.com/glamp/74188691c91d52770807.
Using
docker run -it jupyter/datascience-notebook /bin/bash
command I am able to enter the container. Then I use pip and bash to install the package. All this goes smoothly.I exit the container and commit the changes using the container id.
docker commit containerid imagename
The problem is after committing the changes, when I run the container I am presented with bash prompt instead of the notebook start command.
Is there a way to commit package installation changes without changing the starting command of the image. Alternatively is there a way to edit the container image without actually running the image?

The problem is that you have committed a container that was started with the command /bin/bash.
What you need to is start the container normally using The command that you provided initially adding the -d option to free the terminal:
docker run -it --rm -d --name datascience-notebook -p 8888:8888 -v /home/folder/Projects/:/home/jovyan/Projects -e NB_UID=1000 jupyter/datascience-notebook
Then from the terminal exec into the container and install the contrib extenstions.
docker exec -it datascience-notebook /bin/bash
Exit the container and commit the image:
docker commit datascience-notebook <imagename>
Update:
In case the extension can't be installed when the container is running, the solution is to build a custom Docker image from using a Dockerfile
FROM jupyter/datascience-notebook
RUN <installation commands>
Finally build the image using docker build -t <image-name> . and run the image built.

Related

Run a repository in Docker

I am super new to Docker. I have a repository (https://github.com/hect1995/UBIMET_Challenge.git) I have developed in Mac that want to test it in a Ubuntu environment using Docker.
I have created a Dockerfile as:
FROM ubuntu:18.04
# Update aptitude with new repo
RUN apt-get update \
&& apt-get install -y git
RUN git clone https://github.com/hect1995/UBIMET_Challenge.git
WORKDIR /UBIMET_Challenge
RUN mkdir build
WORKDIR build
RUN cmake ..
RUN make
Now, following some examples I am running:
docker run --publish 8000:8080 --detach --name trial
But I do not see the output of the terminal from the docker to see what is going on. How could I create this docker and check what things I need to add and so on and so forth while inside the docker
TLDR
add '-it' and remove '--detach'
or add ENTRYPOINT in Dockerfile and use docker exec -it to access your container
Longer explanation:
With this command
docker run --publish 8000:8080 --detach --name trial image_name
you tell docker to run image image_name as container named trial, expose port 8080 to host and detach (run in background).
Your Dockerfile does not mention which command should be executed (CMD, ENTRYPOINT), however your image extends 'ubuntu:18.04' image, so docker will run command defined in that image. It's bash.
Your container by default is in non interactive mode so bash has nothing to do and simply exits. Check this with docker ps -a command.
Also you have specified --detach command which tells docker to run container in background.
To avoid this situation you need to remove --detach and add -it (interactive, allocate pseudo-tty). Now you can execute commands in your container.
Next step
Better idea is to set ENTRYPOINT to your application or just hang container with 'sleep infinity' command.
try (sleep forever or run /opt/my_app):
docker run --publish 8000:8080 --detach --name trial image_name sleep infinity
or
docker run --publish 8000:8080 --detach --name trial image_name /opt/my_app
You can also define ENTRYPOINT in your Dockerfile
ENTRYPOINT=sleep infinity
or
ENTRYPOINT=/opt/my_app
then use
docker exec -it trial bash #to run bash on container
docker exec trial cat /opt/app_logs #to see logs
docker logs trial # to see console output of your app
You want to provide and ENTRYPOINT or CMD layer to your docker file I believe.
Right now, it configures itself nicely when you build it - but I'm not seeing any component that points to an executable for the container to do something with.
You're probably not seeing any output because the container 'doesn't do anything' currently.
Checkout this breakdown of CMD: Difference between RUN and CMD in a Dockerfile

running docker container without /bin/bash command

I create docker container with
sudo docker run -it ubuntu /bin/bash
in book The docker book I read
The container only runs for as long as the command we specified, /bin/bash , is running.
didn't I created terminal with option -it and /bin/bash isn't required? will anything change if I don't pass any command in docker run?
You will get the same behavior if you run
sudo docker run -it ubuntu
because the ubuntu docker image specifies /bin/bash as the default command. You can see that in the ubuntu Dockerfile. As #tadman wrote in their answer, providing a command (like /bin/bash) overrides the default CMD.
In addition, -it does not imply a bash terminal. -t allocates a pseudo-tty, and -i keeps STDIN open even if not attached. See the documentation for further details.
That's an override to the default CMD specification. You can run a container with defaults, that's perfectly normal, but /bin/bash is a trick to pop open a shell so you can walk around and check out the built container to see if it's been assembled and configured correctly.

re-running a script in a docker container

I have created a docker image that includes some python code and a shell script that can execute it. It is going to process a bunch of images from the host system.
This command should create a new contaier and run it.
sudo docker run -v /host/folder:/container/folder opencv:latest bash /extract-embeddings.sh
At the end, the container exits. If I type the same command, then another container is created and exited at completion. But how is the correct usage of containers? Should I use restart, start or run (and then clean up exited containers after)? It just seems unnessary to create a new container each time.
I basically just want a docker image containing some code and 3-4 different commands I can execute whenever needed.
And the docker start command doesn't seem to accept "bash /extract-embeddings.sh" as parameters, instead things bash and extract-embeddings.sh are containers. So maybe I am misunderstanding the lifecycle of containers or the usage.
edit:
Got it to work with:
docker run -t -d --name opencv -v /host/folder:/container/folder
docker exec -it opencv bash /extract-embeddings.sh
You can write the Dockerfile to create your docker image and keep the scripts into it-
Dockerfile:
FROM opencv:latest
COPY ./your-script /some_folder
Create image:
docker build -t my_image .
Run your container:
docker run -d --name my_container
Run the script inside the container:
docker exec -it <container_id_or_name> bash /some_folder/your-script
Build your own docker image that starts with opencv:latest and give the command you run as the entrypoint. Dockerfile could be like
FROM opencv:latest
CMD ["/bin/bash", "/extract-embeddings.sh"]
Use docker create to create a named container.
sudo docker create --name=processmyimage -v /host/folder:/container/folder myopencv:latest
Then use docker start each time you want to run it.
sudo docker start processmyimage
This works well if there is only one command you want to run. If there is more than one command, I would take the approach of building an image that runs unrelated command forever (like a tail -f < /dev/null). Then you can use
sudo docker exec -d /bin/bash < cmd-to-run >
for each command

Cannot use vi or vim command in docker container?

It's CentOS 7, already installed vi and vim in my CentOS and I can use them. I run docker in CentOS, when I excute this line below:
docker exec -it mysolr /bin/bash
I cannot use vi/vim in the solr container:
bash: vim: command not found
Why is that and how do I fix it so I can use vi/vim to edit file in docker container?
A typical Docker image contains a minimal set of libraries and utilities to run one specific program. Additionally, Docker container filesystems are not long-lived: it is extremely routine to delete and recreate a container, for instance to use a newer version of a base image.
The upshot of this is that you never want to directly edit files in a Docker container, and most images aren't set up with "rich" editing tools. (BusyBox contains a minimal vi and so most Alpine-based images will too.) If you make some change, it will be lost as soon as you delete the container. (Similarly, you usually can install vim or emacs or whatever, but it will get lost as soon as the container is deleted: installing software in a running container isn't usually a best practice.)
There are two good ways to deal with this, depending on what kind of file it is.
If the file is part of the application, like a source file, edit, debug, and test it outside of Docker space. Once you're convinced it's right (by running unit tests and by running the program locally), docker build a new image with it, and docker run a new container with the new image.
ed config.py
pytest
docker build -t imagename .
docker run -d -p ... --name containername imagename
...
ed config.py
pytest
docker build -t imagename .
docker stop containername
docker run -d -p ... --name containername imagename
If the file is configuration that needs to be injected when the application starts, the docker run -v option is a good way to push it in. You can directly edit the config file on your host, but you'll probably need to restart (or delete and recreate) the container for it to notice.
ed config.txt
docker run \
-v $PWD/config.txt:/etc/whatever/config.txt \
--name containername -p ... \
imagename
...
ed config.txt
docker stop containername
docker rm containername
docker run ... imagename

Docker couchbase cbbackup/cbtransfer/cbrestore tools

I've used docker to install couchbase on my ubuntu machine using (https://hub.docker.com/r/couchbase/server/). The docker run query is as follows:
docker run -d --name db -p 8091-8094:8091-8094 -p 11210:11210 -v /home/dockercontent/couchbase:/opt/couchbase/var couchbase
Everything works perfectly fine. My application connects, I'm able to insert/update and query the couchbase. Now, I'm looking to debug a situation wherein the couchbase is on my co-developers machine who also has the same installation i.e., couchbase on docker using the above link. For achieving this, I wanted to run cbbackup on his installation. To achieve this, I run the following command which is a variation of the above link:
bash -c "clear && docker exec -it couch-db sh"
Can anyone please help me with the location of /opt/couchbase/bin in this setup? I believe this is where I can get access to "cbbackup", "cbrestore" and "cbtransfer" which I can then use to backup and restore data from my colleague's machine.
Thanks,
Abhi.
When you run the command
docker run -d --name db -p 8091-8094:8091-8094 -p 11210:11210 -v /home/dockercontent/couchbase:/opt/couchbase/var couchbase
you're pulling a docker image and spawning a docker container.
Please read more about Docker and containerization.
In order to run cbbackup you need to log into your docker container.
Follow these steps:
Retrieve the container-id:
$ docker ps -a
Look for the CONTAINER ID for IMAGE NAME=couchbase
Login to the container using the command:
$ docker exec -it <container-id> bash
Go to the directory : /opt/couchbase/bin using:
$ cd /opt/couchbase/bin
You'll find cbbackup binary in this directory.

Resources