Simply put, I think docker is going to change the game. Anyone who has any interest whatsoever in devops better be paying attention.
The best part for me about docker is that I can iterate very, very quickly on getting images the way I want. If I am installing a VM, and I screwup a step, reinstalling ubuntu from scratch is no fun. Spinning up a new docker container or image takes less than half a second.
Derek from Scout put it simply and concisely: “Docker is git for deployment”
Here’s what I’ve learned over the past week:
Create a new container by loading a load a fresh image
sudo docker run -i -t ubuntu /bin/bash
Start populating the container with whatever:
apt-get update apt-get install <WHATEVER>
Leave the container
Create a snapshot image of the current state of the container
# grab the container id (this will be the first one in the list) docker ps -a docker commit <CONTAINER_ID> <YOU>/<CONTAINER_NAME>
Run the container as necessary, confifguring ports, using detached mode what not.
At this point you have a docker image (like a snapshot) of a clean install of WHATEVER. Running a container will load the image as a starting point and then allow you to configure as necessary. Screw up the conf file? Just exit the container and start over. The pipeline reversal penalty is minimal.
Launch a fresh container (do one of the following):
sudo docker run -i -t ubuntu:precise /bin/bash
apt-get update #a mounted file systems table to make MySQL happy cat /proc/mounts > /etc/mtab
apt-get install mysql-server
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db # if you want v10.0.x echo "deb http://ftp.osuosl.org/pub/mariadb/repo/10.0/ubuntu precise main" >> /etc/apt/sources.list # if you want v5.5 echo "deb http://ftp.osuosl.org/pub/mariadb/repo/5.5/ubuntu precise main" >> /etc/apt/sources.list apt-get update apt-get install mariadb-server # exit the container exit
Commit the basic install, I like to note which version. Everything after this assumes 5.5, but the basic directions work for 10.0.x as well.
# one of the following: docker commit <container_id> <YOU>/mariadb55 docker commit <container_id> <YOU>/mariadb100
First launch back into a new container, but this time with a data directory mounted. This example uses a host folder at $HOME/mysqldata. Inside the container the directory is mapped to
/data. This makes it easy to spin up different instances of MySQL without having to be constantly configuring new data dirs.
sudo docker run -v="$HOME/mysqldata":"/data" -i -t -p 3306 <YOU>/mariadb55 /bin/bash
THE FOLLOWING FIRST RUN STEPS ASSUMES -v=“$HOME/mysqldata”:“/data” FLAG!
cp /etc/mysql/my.cnf /etc/mysql/my.cnf.orig
Allow access from any ip address. This is obviously not secure for production, but more than enough for this example.
sed -i '/^bind-address*/ s/^/#/' /etc/mysql/my.cnf
Change the data dir
sed -i '/^datadir*/ s|/var/lib/mysql|/data/mysql|' /etc/mysql/my.cnf rm -Rf /var/lib/mysql
Setup new data tables
Follow the prompts (Typically, set a root pw and answer Y for everything else:
Allow docker to login from wherever (Again, obviously not secure for production):
mysql -p --execute="CREATE USER 'docker'@'%' IDENTIFIED BY 'tester';" mysql -p --execute="GRANT ALL PRIVILEGES ON *.* TO 'docker'@'%' WITH GRANT OPTION;"
Bail from the container, back to the host:
mysqladmin -p shutdown exit
In the host, commit and tag:
sudo docker commit -m "mariadb55 image w/ external data" -author="<YOU>" <CONTAINER_ID> amattn/mariadb55 <SOME_TAG>
We can then run with:
sudo docker run -v="$HOME/mysqldata":"/data" -d -p 3306 amattn/mariadb55:<SOME_TAG> /usr/bin/mysqld_safe
See which port is being forwarded with:
sudo docker ps -a
At this point, you can access MariaDB at the host IP address and the forwarded port (usually 49xxx).
Iterate! Did you screw up the
mysql_secure_installation step? Just exit the container and start from your last docker commit. Docker is all about iterating repeatable steps until you have an image ready to go.
There are lots of docker commands. Spend some time browsing the docs:
The two most useful tutorials I came across were:
And an older list of tutorials:
Use tags. The repo format is
<USERNAME>/<IMAGENAME>:<TAG>. I tend name like this:
amattn/component:webappname amattn/postgres92:favstarclone amattn/postgres92:flickrclone amattn/mariadb55:bookmarker amattn/mariadb55:accountmgr