This article is deprecated and no longer maintained.
The techniques in this article are outdated and may no longer reflect Docker best-practices.
For the majority of web applications, it is extremely rare to find the CPU being the culprit for the dropped HTTP requests or choking the web server hosting them. It usually is an under-engineered setup with no caching layer involved, eating up all the resources of the backend data store (i.e. your database of choice).
Memcached - which by now should need no introduction - can increase the performance of your application deployment stack greatly without making any amendments to your available resources (enabling you to squeeze every last bit of its juices).
In this DigitalOcean article, especially keeping in mind those who host multiple web applications (e.g. multiple WordPress instances, Python Applications, etc.), we are going to create docker images to quickly start running (on-demand) Memcached containers which can be operated individually. These containers, kept and secured within their own environments, will work with the application being hosted to help them get better and faster.
The docker project offers higher-level tools, working together, which are built on top of some Linux kernel features. The goal is to help developers and system administrators port applications - with all of their dependencies conjointly - and get them running across systems and machines - headache free.
Docker achieves this by creating safe, LXC (i.e. Linux Containers) based environments for applications called docker containers. These containers are created using docker images, which can be built either by executing commands manually or automatically through Dockerfiles.
Note: To learn more about docker and its parts (e.g. docker daemon, CLI, images etc.), check out our introductory article to the project: docker Explained: Getting Started.
Memcached is a distributed, open-source data storage engine. It was designed to store certain types of data in RAM (instead of slower rate traditional disks) for very fast retrievals by applications, cutting the amount of time it takes to process requests by reducing the number of queries performed against heavier datasets or APIs such as traditional databases (e.g. MySQL).
By introducing a smart, well-planned, and optimized caching mechanism, it becomes possible to handle a seemingly larger amount of requests and perform more procedures by applications. This is the most important use case of Memcached, as it is with any other caching application or component.
Heavily relied upon and used in production for web sites and various other applications, Memcached has become one of the go-to tools for increasing performance without -necessarily - needing to utilize further hardware (e.g. more servers or server resources).
It works by storing keys and their matching values (up to 1 MB in size) onto an associative array (i.e. hash table) which can be scaled and distributed across a large number of virtual servers.
To start using the Docker project on your VPS, you can either use DigitalOcean’s docker image for Ubuntu 13.04 or install it yourself. In this section, we will quickly go over the basic installation instructions for Docker 0.7.1.
Update your droplet:
sudo aptitude update
sudo aptitude -y upgrade
Make sure aufs support is available:
sudo aptitude install linux-image-extra-`uname -r`
Add docker repository key to apt-key for package verification:
sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
Add the docker repository to aptitude sources:
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main\
> /etc/apt/sources.list.d/docker.list"
Update the repository with the new addition:
sudo aptitude update
Finally, download and install docker:
sudo aptitude install lxc-docker
Ubuntu’s default firewall (UFW: Uncomplicated Firewall) denies all forwarding traffic by default, which is needed by docker.
Enable forwarding with UFW:
Edit UFW configuration using the nano text editor.
sudo nano /etc/default/ufw
Scroll down and find the line beginning with DEFAULT_FORWARD_POLICY.
Replace:
DEFAULT_FORWARD_POLICY="DROP"
With:
DEFAULT_FORWARD_POLICY="ACCEPT"
Press CTRL+X and approve with Y to save and close.
Finally, reload the UFW:
sudo ufw reload
Before we begin working with docker, let’s quickly go over its available commands to refresh our memory from our first Getting Started article.
Upon installation, the docker daemon should be running in the background, ready to accept commands sent by the docker CLI. For certain situations where it might be necessary to manually run docker, use the following.
Running the docker daemon:
sudo docker -d &
docker CLI Usage:
sudo docker [option] [command] [arguments]
Note: docker needs sudo privileges in order to work.
Here is a summary of currently available (version 0.7.1) docker commands:
Attach to a running container
Build a container from a Dockerfile
Create a new image from a container’s changes
Copy files/folders from the containers filesystem to the host path
Inspect changes on a container’s filesystem
Get real time events from the server
Stream the contents of a container as a tar archive
Show the history of an image
List images
Create a new filesystem image from the contents of a tarball
Display system-wide information
Insert a file in an image
Return low-level information on a container
Kill a running container
Load an image from a tar archive
Register or Login to the docker registry server
Fetch the logs of a container
Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
List containers
Pull an image or a repository from the docker registry server
Push an image or a repository to the docker registry server
Restart a running container
Remove one or more containers
Remove one or more images
Run a command in a new container
Save an image to a tar archive
Search for an image in the docker index
Start a stopped container
Stop a running container
Tag an image into a repository
Lookup the running processes of a container
Show the docker version information
Building on our knowledge gained from the previous articles in the docker series, let’s dive straight into building a Dockerfile to have docker automatically build Memcached installed images (which will be used to run sandboxed Memcached instances).
Dockerfiles are scripts containing commands declared successively which are to be executed, in the order given, by docker to automatically create a new docker image. They help greatly with deployments.
These files always begin with the definition of a base image by using the FROM command. From there on, the build process starts and each following action taken forms the final with commits (saving the image state) on the host.
Usage:
# Build an image using the Dockerfile at current location
# Tag the final image with [name] (e.g. *nginx*)
# Example: sudo docker build -t [name] .
sudo docker build -t memcached_img .
Note: To learn more about Dockerfiles, check out our article: Docker Explained: Using Dockerfiles to Automate Building of Images.
Copy a file from the host into the container
Set default commands to be executed, or passed to the ENTRYPOINT
Set the default entrypoint application inside the container
Set environment variable (e.g. “key = value”)
Expose a port to outside
Set the base image to use
Set the author / owner data of the Dockerfile
Run a command and commit the ending result (container) image
Set the user to run the containers from the image
Mount a directory from the host to the container
Set the directory for the directives of CMD to be executed
Since Dockerfiles constitute of plain-text documents, creating one translates to launching your favourite text editor and writing the commands you want docker to execute in order to build an image. After you start working on the file, continue with adding all the content below (one after the other) before saving the final result.
Note: You can find what the final Dockerfile will look like at the end of this section.
Let’s create an empty Dockerfile using nano text editor:
nano Dockerfile
We need to have all instructions (commands) and directives listed successively. However, everything starts with building on a base image (set with the FROM command).
Let’s define the purpose of our Dockerfile and declare the base image to use:
############################################################
# Dockerfile to run Memcached Containers
# Based on Ubuntu Image
############################################################
# Set the base image to use to Ubuntu
FROM ubuntu
# Set the file maintainer (your name - the file's author)
MAINTAINER Maintaner Name
After this initial block of commands and declarations, we can begin with listing the instructions for Memcached installation.
# Update the default application repository sources list
RUN apt-get update
# Install Memcached
RUN apt-get install -y memcached
Set the default port to be exposed to outside the container:
# Port to expose (default: 11211)
EXPOSE 11211
Set the default execution command and entrpoint (i.e. Memcached daemon):
# Default Memcached run command arguments
CMD ["-u", "root", "-m", "128"]
# Set the user to run Memcached daemon
USER daemon
# Set the entrypoint to memcached binary
ENTRYPOINT memcached
############################################################
# Dockerfile to run Memcached Containers
# Based on Ubuntu Image
############################################################
# Set the base image to use to Ubuntu
FROM ubuntu
# Set the file maintainer (your name - the file's author)
MAINTAINER Maintaner Name
# Update the default application repository sources list
RUN apt-get update
# Install Memcached
RUN apt-get install -y memcached
# Port to expose (default: 11211)
EXPOSE 11211
# Default Memcached run command arguments
CMD ["-m", "128"]
# Set the user to run Memcached daemon
USER daemon
# Set the entrypoint to memcached binary
ENTRYPOINT memcached
After having everything written inside the Dockerfile, save it and exit by pressing CTRL+X followed by Y.
Using this Dockerfile, we are ready to get started with dockerised Memcached containers!
We can now create our first Memcached image by following the usage instructions explained in the Dockerfile Basics section.
Run the following command to create an image, tagged as “memcached_img”:
sudo docker build -t memcached_img .
Note: Do not forget the trailing .
for docker to find the Dockerfile
.
It is very simple to create any number of perfectly isolated and self-contained memcached instances - now - thanks to the image we have obtained in the previous section. All we have to do is to create a new container with docker run
.
To create a new container, use the following command, modifying it to suit your requirements following this example:
# Example: sudo docker run -name [container name] -p [port to access:port exposed] -i -t [memcached image name]
sudo docker run -name memcached_ins -d -p 45001:11211 memcached_img
Now we will have a docker container named “memcached_ins”, accessible from port 45001, run
using our image tagged “memcached_img”, which we built previously.
In order to limit the amount of memory a docker container process can use, simply set the -m [memory amount]
flag with the limit.
To run a container with memory limited to 256 MBs:
# Example: sudo docker run -name [name] -m [Memory (int)][memory unit (b, k, m or g)] -d (to run not to attach) -p (to set access and expose ports) [image ID]
sudo docker run -name memcached_ins -m 256m -d -p 45001:11211 memcached_img
To confirm the memory limit, you can inspect the container:
# Example: docker inspect [container ID] | grep Memory
sudo docker inspect memcached_ins | grep Memory
Note: The command above will grab the memory related information from the inspection output. To see all the relevant information regarding your container, opt for sudo docker inspect [container ID]
.
There are various ways to try your newly created Memcached running container(s). We will use a simple Python CLI application for this. However, you can just get to production with your application using caching add-ons, frameworks, or libraries.
Make sure that your host has the necessary libraries for Python / Memcached:
sudo apt-get update && sudo apt-get -y upgrade
sudo apt-get install -y python-pip
pip install python-memcached
Let’s create a simple Python script called “mc.py” using nano:
nano cache.py
Copy-and-paste the below (self-explanatory) content inside:
# Import python-memcache and sys for arguments
import memcache
import sys
# Set address to access the Memcached instance
addr = 'localhost'
# Get number of arguments
# Expected format: python cache.py [memcached port] [key] [value]
len_argv = len(sys.argv)
# At least the port number and a key must be supplied
if len_argv < 3:
sys.exit("Not enough arguments.")
# Port is supplied and a key is supplied - let's connect!
port = sys.argv[1]
cache = memcache.Client(["{0}:{1}".format(addr, port)])
# Get the key
key = str(sys.argv[2])
# If a value is also supplied, set the key-value pair
if len_argv == 4:
value = str(sys.argv[3])
cache.set(key, value)
print "Value for {0} set!".format(key)
# If a value is not supplied, return the value for the key
else:
value = cache.get(key)
print "Value for {0} is {1}.".format(key, value)
Press CTRL+X and approve with Y to save and close.
Testing a docker memcached instance using the script above from your host:
# Example: python cache.py [port] [key] [value]
python cache.py 45001 my_test_key test_value
# Return: Value for my_test_key set
# See if the key is set:
python cache.py 45001 my_test_key
# Return: Value for my_test_key is test_value.
For the full set of instructions to install and use docker, check out the docker documentation at docker.io.
<div class=“author”>Submitted by: <a href=“https://twitter.com/ostezer”>O.S. Tezer</a></div>
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
The link to the docs on the bottom of the article is broken (http://docs.docker.io/en/latest/), it should be: https://docs.docker.com/
I think you’re missing a dash in the article:
The name argument needs to be double dashed according to Docker v1.8.3’s documentation.
Great tutorial for getting started with containers. Also have a look at this ebook for learning about docker concepts, deployment and orchestration tools. Docker hands on
Thanks for catching that Harry! I’ll get it fixed asap.
The link to “Docker Explained: Using Dockerfiles to Automate Building of Images.” is broken - it should link to https://www.digitalocean.com/community/articles/docker-explained-using-dockerfiles-to-automate-building-of-images
Hello *Vuk Milicevic,
First of all, I would highly recommend that you check out the “Getting Started with Docker” article. There, I think you will be able to find answers to your question about common scenarios to use docker containers to run application instances. Here is the URL: https://www.digitalocean.com/community/articles/how-to-install-and-use-docker-getting-started
It won’t take more than 30 minutes to go through the article and perhaps an hour or two to really “absorb” all the information. However, in the long run, it will actually save you a lot more time as it’s a great digest of Docker’s fundamentals.
About using x amount of containers running Wordpress sites on a droplet with y amount of RAM:
The benefit you get - first and foremost - consists of isolating these applications from one another and hence, enhancing security on the same system.
Secondly, you can control resources such as amount of RAM these applications are allowed to use.
Third, you can easily deploy a new Wordpress site with a single command from a Docker image you can have built with a Dockerfile.
Finally, to answer your question regarding if a 512 mb droplet would suffice: it all depends on your Wordpress sites. It can be way more than enough or not enough at all - all depending on how you optimise and use these Wordpress installations.
The web server you will use (Apache, Nginx etc.), the amount of “hits” your sites get, the add-ons you will have set-up with Wordpress are some factors to consider when it comes to this.
Good luck!
I’m relatively new to this area. My question is: will a basic 512MB droplet with 5 low/moderately visited WordPress sites have benefit of using 5 containers as described? And, what is the actual best or most common scenario in which these docker instances can be used? I’m so eager to try this out, and would appreciate any further info. Thank you in advance.