How to work with Docker containers: Manually

I usually start with Ubuntu 13.10 and Bash (my repos):

(I know, I’ll have to change 13.10 to 14.04 soon and should use an LTS instead but I like to use the latest and it’s also so easy to rebuild the continers: as easy as changing one line on the top of the Docker file.)

docker run -name mynewcont ubuntu:13.10 bash

If you want to use the container immediatelly, use some additional params like -p and -v too:

docker run -name mynewcont -v /var/www:/var/www -p ubuntu:13.10 bash

There may be some very short time to wait for the image to be downloaded from the Docker’s index.

And now you are inside Ubuntu 13.10 no matter what is running on your host machine.

First thing I like to do is helping df -h and others work:

cat /proc/mounts > /etc/mtab

The next important thing is setting up the mirror system for apt so no matter where your container is started it will fetch the needed packages from the fastest/nearest mirror:

echo "deb mirror:// saucy main restricted universe multiverse" > /etc/apt/sources.list \
&& echo "deb mirror:// saucy-updates main restricted universe multiverse" >> /etc/apt/sources.list \
&& echo "deb mirror:// saucy-backports main restricted universe multiverse" >> /etc/apt/sources.list \
&& echo "deb mirror:// saucy-security main restricted universe multiverse" >> /etc/apt/sources.list

Finally we can update the sources and start installing stuff:

apt-get update && apt-get install -qq nginx-full php5-fpm mysql-server .... etc.

I really like installing and configuring LEMP stacks just for the practice of installing them and seeing the final result 🙂 This will probably convert to: any kind of ruby apps installations in the near future.

After you have installed and configured your server(s) you can just leave the container with them running inside by using the key combo: Ctrl-p + Ctrl+q  – just check if the container is still running after that with: docker ps.

You’ve just built a container like a new virtual machine box: started it clean, installed and ran some software inside, redirected a port, used a shared folder and you’re ready 🙂

What will happen if you restart Docker or the host Docker is running on?

The host will restart, Docker will be started usually automatically and the previously running containers will be started again with the command used to start them in the first place. In our situation this will start our container with bash and that’s it. You’ll have to use some commands to run your server(s) inside the container again:

docker attach mynewcont
/etc/init.d/nginx start (just an example)
( + Ctrl-p + Ctrl-q to detach )

There’s a really nice way to work with that autostart problem and it’s like how the things work here: using Cmd. First, let’s create a new file in the roor of the container’s file system (nginx is just an example):

docker attach mynewcont

Because this example uses nginx and docker needs the last command to be a server started and running in the foreground we need to tell nginx to not daemonize:

NGINXCONFFILE=/etc/nginx/nginx.conf && echo "daemon off;" | cat - $NGINXCONFFILE > $NGINXCONFFILE.tmp && mv $NGINXCONFFILE.tmp $NGINXCONFFILE

Or just put: “daemon off;” at the top of the nginx.conf file with nano or your favorite editor.

Install nano and create a new shell script file:

apt-get install -qq nano
nano /

Enter the follwing inside

#here you may put other things you want to do before the server is started

Ctrl-p + Ctrl-q to detach from the container.

Outside of the container, let’s commit it into a new image:

docker commit -run='{"Cmd":["sh","/"]}' mynewcont iliyan/mynewimg

You can also set the executed command in Cmd to be directly starting the server inside:

docker commit -run='{"Cmd":["/etc/init.d/nginx"]}' mynewcont iliyan/mynewimg

I prefer to always have a way to put additional commands and so I prefer the sh way:


After the commit all changes inside the container are put into the image and will be visible when you run a new container from that image.

Now you have the image which will use to run a new container from. But before that stop/kill and rm the currently running container:

docker stop mynewcont
docker kill mynewcont

And then:

docker rm mynewcont

I just want to create a new container with the same name “mynewcont” and also don’t want the first container which we’re not gonna use anymore.

Now use the image to create and run the container:

docker run -name mynewcont -v /var/www:/var/www -p iliyan/mynewimg

You’ll now have nginx working on localhost:8080 and serving files from the local /var/www path.

Now you see you have to change something inside the container and keep the changes. Let’s make it that way:

Keep the currently running cotainer intact.

Create a new container from the same image the running container is created from. Just don’t use the same volumes and ports, actually don’t use any extra params:

docker run -name mynewcont_tmp iliyan/mynewimg bash

You can also use:

docker run -rm ....

to destroy the container after it’s stopped and will not need to “docker rm …” it later.

Now you may want to add new vhosts in /etc/nginx/sites-available or change the default configuration. Use echo or nginx to create new file/change existing ones.

After the changes are done, detach from the container (Ctrl-p + Ctrl-q) and commit the tmp container over our image with a new tag (tags help starting a container from different configurations made on that image):

docker commit -run='{"Cmd":["sh","/"]}' mynewcont_tmp iliyan/mynewimg:addedmydomain

The tag “addedmydomain” is an example one, you can write anything there to describe tha latest changes. You can later commit with the same tag and different tags using the same image and will have them all listed with:

docker images

You can also see the -run=” param is always used to tell the image what to do. I’ve tested some inheritance without success but after docker updates or my skills improve we may not need to repeat the param.

Now make the procedure with stop/kill and rm of the currently running container:

docker stop mynewcont mynewcont_tmp
docker rm mynewcont mynewcont_tmp

Run the container with the change we made just now:

docker run -name mynewcont -v /var/www:/var/www -p iliyan/mynewimg:addedmydomain

That’s it!

To conclude:

1. We’ve made a container from Ubuntu:13.10 and started Bash inside, installed new packages, ran servers, etc.

2. We attached and detached to/from the container often to make some configuration changes until we were satisfied.

3. Then we committed the container into an image and used that image to run the container again but with the latest changes inside. Before running the same image/container we made sure the currently running one is stopped and removed(remove only if you don’t need to go back to the container for some reason and you want to use the same name to run a new one on its place).

JavaScript: from callback hell through then-hell to generators+promises

Lately I've been refactoring and then refactoring and then some one of my JS apps every time I ...

Learn more

About Iliyan Trifonov

Web Developer, Blogger
Tagged , , , , . Bookmark the permalink.