As I am currently evaluating the three bigger cloud providers (Amazon AWS, Microsoft Azure and Google Cloud Platform) I came up with the idea to test how easy it would be to get Docker running on those providers. In this tutorial I deal with Amazon “AWS”, as I like them most out of the three mentioned.
On 23th of April 2014, Amazon added Docker support for their AWS Elastic Beanstalk, but this time, we will just focus on the EC2, not only due to cost issues.
The idea is to stay with the servers that are available at no charge (The so called “free tier”, which can run 24/7 for free within the first year). Of course, you can go for any other server instance as you like and need.
First we will set-up a small server instance on the EC2 service, followed by the docker set-up and the deployment of one example docker container.
Get the server instance up
- Login to your AWS Management Console
- Choose EC2 – the virtual servers in the Cloud on the Web Services Overview.
- On the next screen, we are going to create a new instance via „Launch instance“.
- You may choose any of the images presented there, but I will go for the Ubuntu Server 14.04 with LTS. Press „Select“ here.
- On the next screen, you can get an overview of the available instances. They are categorized in instance families, like „computing optimized“ or „memory optimized“. Just choose which one you need for your Docker host. In my case I went for the free tier eligible micro instance „t1.micro“ that is powerful enough to test web servers or even a non-powerful Tomcat instance. To configure in detail, just take the „Next: Configure Instance Details“ button here.
- In the next screen, we just select the „Protect against accidental termination“. You may also create a new subnet here, or choose one already existing, so your machines may communicate with each other through an internal network and not through the Internet.
- At the storage page, you can add up to30GB taken from your general purpose SSD to the machine. – Just remove the „delete on termination“, to persist the machine, even after termination. In this case, I added 10GB of space here. Be aware, that these 10 GB actually means that you have 30 IOPS. Those are the maximum input-output operations per second and they scale with the size of your disc. So this will be enough for a small webserver, but of course not for an production system.
- I left the tagging of the instance out. You can add some tags with values here, but they are not needed in this case of setting up a Docker server.
- Step 6 – „Configure Security Group“ will need our attention. What I do here is to configure the ports 80 and 443 (for HTTP and HTTPS) to the outer world, and all other traffic only to my specific IP. This can of course be changed later on. Depending on the desired purpose you can add other specific ports here or setting a tougher security policy. I will for instance log in to the AWS console and change the security rule to my current IP address as often I need it. So, feel free to set it up as you need it and keep this settings in mind when launching Docker containers later on.
- After that you will see a summary, where you are able to launch your new configured instance. Just check, that everything was configured the right way and press “Launch” in the lower right corner.
- You will be asked about the way you would like to connect to your machine. If this is the first time, setting a machine up, you have to choose “Create a new Key Pair” here. Give it a speaking name and download the key pair to your computer to a save place and make a backup of them. You will need it every time to connect to your server instance. In my case, the key file is named MyDockerInstance.pem. I have those files stored in a encrypted container file created by Truecrypt. You might secure this file.
- After pressing “Launch instances”, open your Current running instances. You will see your currently set-up instance initializing.
In the table above, you will also find the currently assigned public IP through which we can connect to the machine, when the instance state is switching to “running”.
First connection to your newly created machine
To connect to the just created virtual machine we will utilize Putty. Depending on your operating system you might have to choose another method. As I am currently working under Windows, I went for this way. Just search for „ssh connection pem <your operating system>“ to find a proper way to connect via SSH to the machine.
When installing Putty, also install Putty Key Generator, as this software is needed to import the OpenSSH SSH-2 private key and save it as a private key, so Putty can use this newly created connection file for the connection.
- Open Putty Gen and Select „File -> Open“. When selecting your Key, you will see the following notice:
- I strongly advise you to add a key phrase here to enhance security. After that select „Save Private Key“
- In the next step, we will save the connection to Putty. First, open Putty and open Data under the Connection settings. Add „ubuntu“ as a user name here (only valid, when you have choosen Ubuntu as your template for the machine creation).
- In the SSH – Auth settings, load your private key file
- Now switch to the session settings and enter add your public IP address and save the session for later use.
- Choose “open” and accept the following security alert:
- In the following screen, enter your passphrase and press Enter. You are now connected to your virtual Ubuntu server running on Amazons EC2 service.
After the installation and first login to our newly created server it is the time to get Docker running. First, we update the sources, followed by installing the docker.io package.
ubuntu@ip-172-31-18-33:~$ sudo apt-get update Ign http://eu-west-1.ec2.archive.ubuntu.com trusty InRelease Ign http://eu-west-1.ec2.archive.ubuntu.com trusty-updates InRelease Get:1 http://eu-west-1.ec2.archive.ubuntu.com trusty Release.gpg[933 B] Get:2 http://eu-west-1.ec2.archive.ubuntu.com trusty-updates Release.gpg [933 B] Get:3 http://eu-west-1.ec2.archive.ubuntu.com trusty Release [58.5 kB] Get:4 http://eu-west-1.ec2.archive.ubuntu.com trusty-updates Release [58.5 kB] Ign http://security.ubuntu.com trusty-security InRelease Get:5 http://eu-west-1.ec2.archive.ubuntu.com trusty/main Sources [1,064 kB] Get:6 http://security.ubuntu.com trusty-security Release.gpg [933 B] Get:7 http://eu-west-1.ec2.archive.ubuntu.com trusty/universe Sources [6,399 kB] Get:8 http://security.ubuntu.com trusty-security Release [58.5 kB] Get:9 http://security.ubuntu.com trusty-security/main Sources [20.6 kB] Get:10 http://eu-west-1.ec2.archive.ubuntu.com trusty/main amd64 Packages [1,350 kB] Get:11 http://security.ubuntu.com trusty-security/universe Sources [4,727 B] Get:12 http://security.ubuntu.com trusty-security/main amd64 Packages [61.3 kB] Get:13 http://eu-west-1.ec2.archive.ubuntu.com trusty/universe amd64 Packages [5,859 kB] Get:14 http://security.ubuntu.com trusty-security/universe amd64 Packages [21.5 kB] Get:15 http://security.ubuntu.com trusty-security/main Translation-en [29.9 kB] Get:16 http://security.ubuntu.com trusty-security/universe Translation-en [11.3 kB]
Running this command will additionaly load some other packages that are needed to get Docker running:
ubuntu@ip-172-31-18-33:~$ sudo apt-get install docker.io Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: aufs-tools cgroup-lite git git-man liberror-perl Suggested packages: btrfs-tools debootstrap lxc rinse git-daemon-run git-daemon-sysvinit git-doc git-el git-email git-gui gitk gitweb git-arch git-bzr git-cvs git-mediawiki git-svn The following NEW packages will be installed: aufs-tools cgroup-lite docker.io git git-man liberror-perl 0 upgraded, 6 newly installed, 0 to remove and 63 not upgraded. Need to get 7,096 kB of archives. After this operation, 44.2 MB of additional disk space will be used. Do you want to continue? [Y/n] Y
Setting an symbolic link from docker.io to the docker executable
ubuntu@ip-172-31-18-33:~$ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
After that, we will just add the docker binary to the bash completion, so we can „tab“ through the possible parameters when typing the docker command on command line:
ubuntu@ip-172-31-18-33:~$ sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io
The next and last step will run /bin/bash terminal inside of a standard Ubuntu image. As the image wasn´t downloaded so far, it will be pulled from the repository. When this process is finished, we will directly connect to the newly created docker instance as root. To leave the instance later on, just type „exit“ on the command line and you will be back to your host system.
ubuntu@ip-172-31-18-33:~$ sudo docker run -i -t ubuntu /bin/bash Unable to find image 'ubuntu' locally Pulling repository ubuntu […] root@ffed5fefcca3:/#
Example of setting up a simple nginx container
To set up a nginx web server on docker, you might create a Dockerfile by your own or (in first stage) rely on other people who already did this process for you. In this tutorial, I simple run a docker container from the user „orchardup“. You can find additional information on the docker-nginx github page.
First, we clone the git repository to our server:
ubuntu@ip-172-31-18-33:/data$ sudo git clone https://github.com/orchardup/docker-nginx Cloning into 'docker-nginx'... remote: Reusing existing pack: 19, done. remote: Total 19 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (19/19), done. Checking connectivity... done.
Second, we will build the container from the newly created Dockerfile in the sub-folder „docker-nginx“.
ubuntu@ip-172-31-18-33:/data/docker-nginx$ sudo docker build -t nginx-test . Uploading context 92.16 kB Uploading context Step 0 : FROM stackbrew/ubuntu:12.04 Pulling repository stackbrew/ubuntu […] ---> ebe4be4dd427 Step 1 : MAINTAINER Ben Firshman "firstname.lastname@example.org" ---> Running in 6e8fde334b78 ---> 7d592d26526a
After that building process, we can run the server:
ubuntu@ip-172-31-18-33:/data/docker-nginx$ sudo docker run -p 80:80 -d nginx-test 8cb2e531f2d49fbef4487571290af0be72c1734883b6b95ebbb0457eaf153896 ubuntu@ip-172-31-18-33:/data/docker-nginx$ curl localhost <html> <head><title>500 Internal Server Error</title></head> <body bgcolor="white"> <center><h1>500 Internal Server Error</h1></center> <hr><center>nginx/1.1.19</center> </body> </html> ubuntu@ip-172-31-18-33:/data/docker-nginx$
If you connect to your machine, it will look like the following, as no content was added to the /var/www directory:
To change this, we will slightly change the Dockerfile and run the build process again.
The following command will add a additional „RUN“ command to the Dockerfile. This command will add a file in the web server root directory and fill this file with content.
ubuntu@ip-172-31-18-33:/data/docker-nginx$ sudo sed '9iRUN mkdir /var/www & echo "test page running on docker" > /var/www/index.html' Dockerfile -i
So we are stopping the currently running container, rebuild it and than run it again in the next steps. The following command unhides the container ID, so we can stop the container after that.
ubuntu@ip-172-31-18-33:/data/docker-nginx$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8cb2e531f2d4 nginx-test:latest nginx About an hour ago Up About an hour 0.0.0.0:80->80/tcp pensive_turing
Stopping the container, by knowing its ID:
ubuntu@ip-172-31-18-33:/data/docker-nginx$ sudo docker stop 8cb2e531f2d4 8cb2e531f2d4
Now we are going to rebuild the container, just as before. You will recognize, that the container is created from cache with very low latency. It will be available almost instantly.
ubuntu@ip-172-31-18-33:/data/docker-nginx$ sudo docker build -t nginx-test . Uploading context 92.16 kB Uploading context Step 0 : FROM stackbrew/ubuntu:12.04 ---> ebe4be4dd427 Step 1 : MAINTAINER Ben Firshman "email@example.com" ---> Using cache ---> 7d592d26526a Step 2 : RUN apt-get update -qq && apt-get -y install nginx ---> Using cache ---> 0ccfb0aefe91 Step 3 : RUN echo "daemon off;" >> /etc/nginx/nginx.conf ---> Using cache ---> b697a3929004 Step 4 : RUN mkdir /etc/nginx/ssl ---> Using cache ---> 9b1c9a72de25 Step 5 : ADD default /etc/nginx/sites-available/default ---> Using cache ---> 51eb0c8540f6 Step 6 : ADD default-ssl /etc/nginx/sites-available/default-ssl ---> Using cache ---> 1316ef1cac80 Step 7 : RUN mkdir /var/www ---> Using cache ---> 3fdb134dea09 Step 8 : RUN echo "test page running on docker" > /var/www/index.html ---> Using cache ---> 6ab8f01d7674 Step 9 : EXPOSE 80 ---> Running in 991eb7949c4a ---> ff123b5ce755 Step 10 : CMD ["nginx"] ---> Running in 84110614b631 ---> 7bbe60073b4d Successfully built 7bbe60073b4d Removing intermediate container 991eb7949c4a Removing intermediate container 84110614b631
In the last two steps, we are going to run the container and check, if the newly created index.html is available or not:
ubuntu@ip-172-31-18-33:/data/docker-nginx$ sudo docker run -p 80:80 -d nginx-test c4ad018d822cd3d641878f5d004a778d38a4ebbfcd6ab38bf16d19ee7721973d
With curl, we test that the web server is serving our new page.
ubuntu@ip-172-31-18-33:/data/docker-nginx$ curl localhost test page running on docker
Im conclusion to this tutorial, we set-up a micro server instance on Amazon EC2 service and installed Docker.io there. In addition we launched an simple nginx web server, serving a static html file.