This tutorial is part of this book and through it, we are going to discover how to use Rancher in order to create a scalable _Wordpress_ application. ### Rancher Architecture In _Rancher_, everything (like containers, networks or images ) is an _API_ resource with a process lifecycle. Containers, images, networks, and accounts are all _API_ resources with their own process lifecycles. Rancher is built on the top of containers: * A web _UI_ * An _API_ * A server that manages _Rancher Agents_ * A database * A machine microservice * The _docker-machine_ binary  Rancher Server Architecture When you run _Rancher_ using `docker run rancher/server ...` the _Rancher_ _API_ + _Rancher Process Server_ + The Database + _Machine Microservice_ are processes that live inside this container. Note that the docker-machine binary is also living in the same container but only runs when it is called by the _API_. _Rancher_ has also an Agent part that manages the life cycle of containers. If `docker-machine` creates a machine successfully, some events are exchanged between the `docker-machine` and the microservice. A _bootstrap_ event is created and a `docker-machine config`command is executed to get the details needed to connect to the machine’s Docker daemon. If everything run without problems, the service fires up a _Rancher Agent_ on the machine via docker run rancher/agent … _Rancher Agents_ open a _WebSocket_ connection to the server in order to establish a 2-way communication. The _Rancher Agent_ manage its containers and reports every change using the Docker _API_. During this tutorial, we are going to use an _EC2_ machine and this is how a different view of the layers of our _Rancher_ installation:  RancherOS Architecture ### RancherOS _RancherOS_ is a small distribution released by _Rancher_ team. It is an easy way to run containers at scale in production and includes only the services needed to run Docker. It only includes the latest version of Docker and removes any unneeded library that a “normal” _Linux_ distribution could have. In _RancherOS_, everything is a container, the traditional _init_ system is replaced so that Docker run directly on the _Kernel_. A special component in this system is called _User Docker_ which is the daemon that allow a user (a non-system user) runs its containers.  RancherOS Architecture We are going to run _RancherOS_ in an _EC2_ machine using _AWS_ _CLI_: aws ec2 run-instances --image-id ami-ID --count 1 --instance-type t2.micro --key-name MySSHKeyName --security-groups sg-name This is the list of AMI by region:  Now you can login to your machine using the _AWS_ common _ssh_ command : ssh -i "MySSHKeyName" rancher@xxxx.xx-xxxx-x.compute.amazonaws.com ### Running Rancher Since Docker is installed by default, we can start using it directly. Let’s start a _MariaDB_ server then use it with _Rancher Server_. docker run --name mariadb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=cattle -e MYSQL_USER=cattle -e MYSQL_PASSWORD=cattle -p 3306:3306 -d mariadb Run the _Rancher Server_ and change 172.31.0.190 by your _MariaDB_ _IP_: docker run --name rancher_server -p 8080:8080 -e CATTLE_DB_CATTLE_MYSQL_HOST=172.31.0.190 -e CATTLE_DB_CATTLE_MYSQL_PORT=3306 -e CATTLE_DB_CATTLE_MYSQL_NAME=cattle -e CATTLE_DB_CATTLE_USERNAME=cattle -e CATTLE_DB_CATTLE_PASSWORD=cattle -v /var/run/docker.sock:/var/run/docker.sock -d rancher/server Now you can go to your `<host_ip>:8080` and add a _Linux_ host with a supported version of Docker:  Adding A Rancher Host We are not going to use the public _IP_ address but the private (_eth0_) one.  Adding A Rancher Host Let’s add a custom host. A command is given to run on any reachable host in order to let it join the server. At this step, I already created an _EC2_ machines (with _RancherOS_ as an operating system) and I am going to use it and run this command: sudo docker run -d --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.1 http://172.31.0.190:8080/v1/scripts/02048221239BE78134BB:1483142400000:i5yrQRE4kFo7eIKz9n1o5VFTew Make sure any _Security Groups_ or _firewalls_ allow traffic from and to all other hosts on _UDP_ ports 500 and 4500. After the _Agent_ installation, we can notice that some containers are running in each _Agent_ machine like the _dns_, _healthcheck_, _network-manager_ ..: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES8339a8af3bb8 rancher/net:v0.9.4 "/rancher-entrypoint." About a minute ago Up About a minute r-ipsec-ipsec-router-1-19bd25e395f3d3afdb7c rancher/net:holder "/.r/r /rancher-entry" About a minute ago Up About a minute r-ipsec-ipsec-1-90844ad45643089ca485 rancher/healthcheck:v0.2.3 "/.r/r /rancher-entry" 2 minutes ago Up 2 minutes r-healthcheck-healthcheck-1-91ae658dfec564c53f13 rancher/dns:v0.14.1 "/rancher-entrypoint." 2 minutes ago Up 2 minutes r-network-services-metadata-dns-1-471d9deac162c07d07f6 rancher/net:v0.9.4 "/rancher-entrypoint." 2 minutes ago Up 2 minutes r-ipsec-ipsec-cni-driver-1-e02f6a010313ff5cb812 rancher/scheduler:v0.7.5 "/.r/r /rancher-entry" 2 minutes ago Up 2 minutes r-scheduler-scheduler-1-5ca518560f6f62a190c7 rancher/network-manager:v0.5.3 "/rancher-entrypoint." 2 minutes ago Up 2 minutes r-network-services-network-manager-1-03d3f619ec270864ff07 rancher/metadata:v0.8.11 "/rancher-entrypoint." 2 minutes ago Up 2 minutes r-network-services-metadata-1-4be6ebc698a78058bc3c rancher/agent:v1.2.1 "/run.sh run" 2 minutes ago Up 2 minutes rancher-agent ### Running A Wordpress Service If everything is ok, we are going to create a _Wordpress_ service. Go to _Stack_ menu and click _User_. Create the _MariaDB_ database, name it _wordpressdb_ (we are going to use it in order to link it to the _Wordpress_ container)  Then add your environment variables:  Now, using the same way, create the _Wordpress_ container, map host port 80 to the container port 80 and link the _mariadb_ container as a _mysql_ instance.  Then add your environment variables:  At this step, we can check the running services, use _Stack_\->_User_ then _default_ to see the containers:  What we started is the equivalent of 2 docker commands, one to start the _mariadb_ container and the other one to start the _wordpress_ container. You can visit the _Wordpress_ fresh installation using its _IP_ address. We can see the details of the different configurations a running container could have if you choose the container from the same view then use the “_View in API_” menu. This is an example of the _wordpress_ container: { "id":"1s7", "type":"service", "links":{ "self":"…/v2-beta/projects/1a5/services/1s7", "account":"…/v2-beta/projects/1a5/services/1s7/account", "consumedbyservices":"…/v2-beta/projects/1a5/services/1s7/consumedbyservices", "consumedservices":"…/v2-beta/projects/1a5/services/1s7/consumedservices", "instances":"…/v2-beta/projects/1a5/services/1s7/instances", "networkDrivers":"…/v2-beta/projects/1a5/services/1s7/networkdrivers", "serviceExposeMaps":"…/v2-beta/projects/1a5/services/1s7/serviceexposemaps", "serviceLogs":"…/v2-beta/projects/1a5/services/1s7/servicelogs", "stack":"…/v2-beta/projects/1a5/services/1s7/stack", "storageDrivers":"…/v2-beta/projects/1a5/services/1s7/storagedrivers", "containerStats":"…/v2-beta/projects/1a5/services/1s7/containerstats" }, "actions":{ "upgrade":"…/v2-beta/projects/1a5/services/1s7/?action=upgrade", "restart":"…/v2-beta/projects/1a5/services/1s7/?action=restart", "update":"…/v2-beta/projects/1a5/services/1s7/?action=update", "remove":"…/v2-beta/projects/1a5/services/1s7/?action=remove", "deactivate":"…/v2-beta/projects/1a5/services/1s7/?action=deactivate", "removeservicelink":"…/v2-beta/projects/1a5/services/1s7/?action=removeservicelink", "addservicelink":"…/v2-beta/projects/1a5/services/1s7/?action=addservicelink", "setservicelinks":"…/v2-beta/projects/1a5/services/1s7/?action=setservicelinks" }, "baseType":"service", "name":"wordpress", "state":"active", "accountId":"1a5", "assignServiceIpAddress":false, "createIndex":1, "created":"2017-04-04T21:05:53Z", "createdTS":1491339953000, "currentScale":1, "description":"wordpress files", "externalId":null, "fqdn":null, "healthState":"healthy", "instanceIds":\[ "1i14" \], "kind":"service", "launchConfig":{ "type":"launchConfig", "capAdd":\[ \], "capDrop":\[ \], "dataVolumes":\[ \], "dataVolumesFrom":\[ \], "devices":\[ \], "dns":\[ \], "dnsSearch":\[ \], "environment":{ "WORDPRESS\_DB\_NAME":"wordpress", "WORDPRESS\_DB\_USER":"wordpress", "WORDPRESS\_DB\_PASSWORD":"wordpress" }, "imageUuid":"docker:wordpress", "instanceTriggeredStop":"stop", "kind":"container", "labels":{ "io.rancher.container.pull\_image":"always" }, "logConfig":{ "type":"logConfig", "config":{ }, "driver":"" }, "networkMode":"managed", "ports":\[ "80:80/tcp" \], "privileged":false, "publishAllPorts":false, "readOnly":false, "secrets":\[ \], "startOnCreate":true, "stdinOpen":true, "system":false, "tty":true, "version":"0", "dataVolumesFromLaunchConfigs":\[ \], "vcpu":1 }, "lbConfig":null, "linkedServices":{ "mysql":"1s6" }, "metadata":null, "publicEndpoints":\[ { "type":"publicEndpoint", "hostId":"1h1", "instanceId":"1i14", "ipAddress":"54.246.163.197", "port":80, "serviceId":"1s7" } \], "removed":null, "retainIp":null, "scale":1, "scalePolicy":null, "secondaryLaunchConfigs":\[ \], "selectorContainer":null, "selectorLink":null, "stackId":"1st5", "startOnCreate":true, "system":false, "transitioning":"no", "transitioningMessage":null, "transitioningProgress":null, "upgrade":null, "uuid":"0b8a8290-0d10-47be-b182-45f1e57e80bc", "vip":null } We can also inspect other services and hosts configurations in the same way. ### Cattle: The Rancher Container Orchestrator What we started below is _Rancher_ powered by its own orchestration tool called _Cattle_. Rancher offers the possibility to use other orchestration tools like _Kubernetes_, _Docker Swarm_ or _Mesos_. _Cattle_ is a container orchestration and scheduling framework, in its beginning, it was designed as an extension to _Docker Swarm_ but since _Docker Swarm_ continues to develop, _Cattle_ and _Swarm_ started to diverge. _Cattle_ is used extensively by _Rancher_ itself to orchestrate infrastructure services as well as setting up, managing, and upgrading _Swarm_, _Kubernetes_, and _Mesos_ clusters. _Cattle_ application deployments are organized into _stacks_ which can be used to _User_ or _Infrastructure_ stacks. A _Cattle_ _Stack_ is a collection of _Services_ and the latter is primarily a Docker image with its networking, scalability, storage, health checks, service discovery links, environment and all of the other configurations. A _Cattle_ _Service_ could be a load balancer or an external service. A _Stack_ can be launched using a _docker-compose.yml_ or _rancher-compose.yml_ file or just start containers like we did for the _Wordpress_ stack. In addition to this, you can start several applications using an application catalog. More than 50 different apps are available in the app catalog. An application is defined by a _docker-compose_ and a _rancher-compose_ file and can be deployed easily with the default configurations. Let’s take the example of _Portainer_: > _Portainer is a lightweight management UI which allows you to easily manage your Docker host or Swarm cluster. > Portainer is meant to be as simple to deploy as it is to use. It consists of a single container that can run on any Docker engine (Docker for Linux and Docker for Windows are supported). > Portainer allows you to manage your Docker containers, images, volumes, networks and more ! It is compatible with the standalone Docker engine and with Docker Swarm._ This is the `docker-compose.yml` file of _Portainer_: portainer: labels: io.rancher.sidekicks: ui io.rancher.container.create_agent: true io.rancher.container.agent.role: environment image: rancher/portainer-agent:v0.1.0 volumes: - /config ui: image: portainer/portainer:pr572 command: --no-auth --external-endpoints=/config/config.json --sync-interval=5s -p :80 volumes_from: - portainer net: container:portainer This is its `rancher-compose.yml` file: .catalog: name: "Portainer" version: "1.11.4" description: Open-source lightweight management UI for a Docker host or Swarm cluster minimum_rancher_version: v1.5.0-rc1  Starting Portainer Rancher offers the possibility to start infrastructure _Stacks_. If you go to _Stacks_\->_Infrastructure_, you can see a catalog of tools like _Bind9_, _Portainer_, _Rancher vxlan_ ..etc  Infrastructure Catalog ### Scaling Wordpress Using Rancher Now we want to scale our _Wordpress_ frontal app in order to handle more traffic. In this case, you should click _Stack_\->_User_ then the name of the _Stack_ (it should be the default one if you followed this tutorial as it is). Now click on _Wordpress_ and scale your app to 3 containers:  At this step, you should see how _Wordpress_ won’t scale the right way. This is normal since all of our _Wordpress_ containers are mapped to the same port 80 (that can handle only one container). In order to scale _Wordpress_ the right way, we should tell Rancher to create a load balancer service with auto-discovery and let _Rancher_ choose the _Wordpress_ container port automatically. This part is detailed in [Painless Docker Book](http://painlessdocker.com). ### Connect Deeper This article is part of [Painless Docker Book: Unlock The Power Of Docker & Its Ecosystem](http://painlessdocker.com/). [Painless Docker](http://painlessdocker.com) is a practical guide to master **Docker** and **its ecosystem** based **on real-world examples**. [](http://painlessdocker.com) Painless Docker tends to be a complete and detailed guide to create, deploy, optimize, secure, trace, debug, log, orchestrate & monitor Docker and Docker clusters. Through this book, you will learn how to use Docker in development and production environments and the DevOps pipeline between them in order to build modern microservices applications. If you resonated with this article, please subscribe to [DevOpsLinks](http://devopslinks.com) : An Online Community Of Diverse & Passionate DevOps, SysAdmins & Developers From All Over The World. You can find me on [Twitter](https://twitter.com/eon01) and you can also check my books: [SaltStack For DevOps](http://saltstackfordevops.com) & [Painless Docker](http://painlessdocker.com).  If you liked this post, please recommend and share it with your followers.