Docker - WordPress Deploy to ECS with Docker-Compose (ECS-CLI EC2 type)
We can use Docker Compose files in any format (v1, v2, or v3) to deploy containers using the Amazon ECS CLI (Amazon ECS CLI Supports Docker Compose Version 3).
Let's install ECS CLI (Amazon ECS Command Line Reference) on Mac (Installing the Amazon ECS CLI):
$ sudo curl -o /usr/local/bin/ecs-cli https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-darwin-amd64-latest
Verify the downloaded binary with the MD5 sum provided. Compare the two output strings (the checksum that is returned from local md5 run should match the from on the S3 source):
$ curl -s https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-darwin-amd64-latest.md5 && md5 -q /usr/local/bin/ecs-cli 4ff2288545af59bb2e68750a45d5ac00 4ff2288545af59bb2e68750a45d5ac00
Apply execute permissions to the binary:
$ sudo chmod +x /usr/local/bin/ecs-cli
Verify that the CLI is working properly by checking the versio:
$ ecs-cli --version ecs-cli version 1.12.1 (e70f1b1)
The Amazon ECS CLI requires some basic configuration information (Configuring the Amazon ECS CLI) before we can use it, such as our AWS credentials, the AWS Region in which to create our cluster, and the name of the Amazon ECS cluster to use.
Starting from v1.0.0, the new YAML formatted configuration files are splitt into two separate files. Credential information is stored in ~/.ecs/credentials and cluster configuration information is stored in ~/.ecs/config.
Set up a CLI profile with the following command, substituting profile_name with desired profile name, $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY environment variables with our AWS credentials. Let's set "wordpress" as a default profile:
$ ecs-cli configure profile --profile-name wordpress --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY $ cat ~/.ecs/credentials version: v1 default: wordpress ecs_profiles: wordpress: aws_access_key_id: AKIAIY6RID2W2C5I3P5Q aws_secret_access_key: KLjk4Axhz1N2852p0r9iTvn2aJltNOjSQCIygVjb
If we want to set a default config-name, follow this example below which configures the Amazon ECS CLI to set the ec2-tutorial cluster configuration as the default.
$ ecs-cli configure default --config-name ec2-tutorial
$ cat ~/.ecs/config version: v1 default: ec2-tutorial clusters: ec2-tutorial: cluster: ec2-tutorial region: us-east-1 default_launch_type: EC2 wordpress: cluster: wordpress region: us-east-1 default_launch_type: EC2
Then, create a cluster configuration:
ecs-cli configure --cluster cluster_name --default-launch-type launch_type --region region_name --config-name configuration_name $ ecs-cli configure --cluster wordpress --region us-east-1 --default-launch-type EC2 --config-name wordpress
The ecs-cli configure command configures the AWS Region to use, resource creation prefixes, and the Amazon ECS cluster name to use with the Amazon ECS CLI. Stores a single named cluster configuration in the ~/.ecs/config file. The first cluster configuration that is created is set as the default.
$ cat ~/.ecs/config version: v1 default: wordpress clusters: wordpress: cluster: wordpress region: us-east-1 default_launch_type: EC2
The next action we should take is to create a cluster of Amazon ECS container instances that we can launch our containers on with the ecs-cli up command.
The ecs-cli up command creates the Amazon ECS cluster (if it does not already exist) and the AWS resources required to set up the cluster (ecs-cli up).
This command creates a new AWS CloudFormation stack called amazon-ecs-cli-setup-cluster_name. We can view the progress of the stack creation in the AWS Management Console.
The following command brings up a cluster of 1 t2.micto instance and configures them to use the EC2 key pair provided. It will use EC2 Launch Type. The name of the cluster is set to wordpress. Note that we use a keypair einsteinish.pem but without the pem extension. Otherwise, we may get the keypair does not exist error:
$ ecs-cli up --keypair einsteinish --capability-iam --size 1 --instance-type t2.micro --cluster wordpress INFO[0001] Using recommended Amazon Linux 2 AMI with ECS Agent 1.22.0 and Docker version 18.06.1-ce INFO[0006] Created cluster cluster=wordpress region=us-east-1 INFO[0007] Waiting for your cluster resources to be created... INFO[0007] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS INFO[0069] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS INFO[0131] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS VPC created: vpc-0788e613566d307e5 Security Group created: sg-01a20a06be03b7b4d Subnet created: subnet-08dce2099d47fb07c Subnet created: subnet-0e5aca767db43b163 Cluster creation succeeded.
Here is the resources created via Cloudformation:
The resources were created using the following parameters:
Note that we used the --force param to let Cloudformation know that we need a complete stack recreation (in case when we already have a previous stack and we want to replace it).
Warning - the "--cluster-config wordpress" does not seem to take the correct cluster_name (it takes ecs-demo-cluste as the culster's name instead). So, in the command, I had to specify the name with "--cluster wordpress".
As mentioned earlier, the Cloudformation prepended "amazon-ecs-cli-setup-" to the specified parameter provided, "wordpress". So, the name is "amazon-ecs-cli-setup-wordpress".
Now, we created our cluster:
For this step, we'll create a simple Docker compose file that creates a WordPress application consisting of a web server and a MySQL database. At this time, the Amazon ECS CLI supports Docker compose file syntax versions 1, 2, and 3.
Here is our compose file (docker-compose.yml) from Tutorial: Creating a Cluster with an EC2 Task Using the Amazon ECS CLI:
version: '3' services: wordpress: image: wordpress ports: - "80:80" links: - mysql mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: password
When using Docker Compose version 3 format, the CPU and memory specifications must be specified separately. Create a file named ecs-params.yml with the following content:
version: 1 task_definition: services: wordpress: cpu_shares: 100 mem_limit: 262144000 mysql: cpu_shares: 100 mem_limit: 262144000
Note that each container has 100 CPU units and 250 MiB of memory. The wordpress container exposes port 80 to the container instance for inbound traffic to the web server.
Now that we created the compose file, we can deploy it to our cluster with the ecs-cli compose up command. By default, the command looks for a compose file (docker-compose.yml) and an optional ECS parameters file (ecs-params.yml) in the current directory, but we can specify a different file with the --file option.
By default, the resources created by this command have the current directory in the title, but we can override that with the --project-name project_name option.
$ ecs-cli compose up --cluster wordpress --cluster-config wordpress --force-update INFO[0001] Using ECS task definition TaskDefinition="ECS-WORDPRESS:6" INFO[0001] Starting container... container=3f479b81-8c44-48c9-ac66-12d62828f19d/wordpress INFO[0001] Starting container... container=3f479b81-8c44-48c9-ac66-12d62828f19d/mysql INFO[0002] Describe ECS container status container=3f479b81-8c44-48c9-ac66-12d62828f19d/wordpress desiredStatus=RUNNING lastStatus=PENDING taskDefinition="ECS-WORDPRESS:6" INFO[0002] Describe ECS container status container=3f479b81-8c44-48c9-ac66-12d62828f19d/mysql desiredStatus=RUNNING lastStatus=PENDING taskDefinition="ECS-WORDPRESS" INFO[0015] Describe ECS container status container=3f479b81-8c44-48c9-ac66-12d62828f19d/wordpress desiredStatus=RUNNING lastStatus=PENDING taskDefinition="ECS-WORDPRESS:6" INFO[0015] Describe ECS container status container=3f479b81-8c44-48c9-ac66-12d62828f19d/mysql desiredStatus=RUNNING lastStatus=PENDING taskDefinition="ECS-WORDPRESS" INFO[0027] Stopped container... container=3f479b81-8c44-48c9-ac66-12d62828f19d/wordpress desiredStatus=STOPPED lastStatus=STOPPED taskDefinition="ECS-WORDPRESS:6" INFO[0027] Stopped container... container=3f479b81-8c44-48c9-ac66-12d62828f19d/mysql desiredStatus=STOPPED lastStatus=STOPPED taskDefinition="ECS-WORDPRESS"
After we deploy the compose file, we can view the containers that are running on our cluster with the ecs-cli ps command:
$ ecs-cli ps --cluster wordpress Name State Ports TaskDefinition Health ce7fc5a3-b8a4-4790-a762-3d455e5b755b/wordpress RUNNING 34.236.237.178:80->80/tcp ECS-WORDPRESS UNKNOWN ce7fc5a3-b8a4-4790-a762-3d455e5b755b/mysql RUNNING ECS-WORDPRESS UNKNOWN
We can see the wordpress and mysql containers from our compose file, and also the IP address and port of the web server. If we point a web browser to that address, we should see the WordPress installation wizard.
Modifies the number of container instances in our cluster. This command changes the desired and maximum instance count in the Auto Scaling group created by the ecs-cli up command. We can use this command to scale out (increase the number of instances) or scale in (decrease the number of instances) our cluster:
$ ecs-cli scale --capability-iam --size 2 --cluster wordpress
A Task launches containers that's defined in the task definition until they are stopped or exit on their own, at which point they are not replaced automatically. We can use Service to guarantee that we always have some number of tasks running at all times. If ECS container instance or Task's container fails the ECS Service will replace the failed Task.
Let's bring down the tasks and then run it as an ECS service to keep a desired count of 1:
To bring down the tasks:
$ ecs-cli compose down --cluster wordpress --cluster-config wordpress INFO[0001] Stopping container... container=2ea5175d-e957-467e-8fd1-4b66d2a4a9c3/wordpress INFO[0001] Stopping container... container=2ea5175d-e957-467e-8fd1-4b66d2a4a9c3/mysql INFO[0001] Describe ECS container status container=2ea5175d-e957-467e-8fd1-4b66d2a4a9c3/wordpress desiredStatus=STOPPED lastStatus=RUNNING taskDefinition="ECS-WORDPRESS" INFO[0001] Describe ECS container status container=2ea5175d-e957-467e-8fd1-4b66d2a4a9c3/mysql desiredStatus=STOPPED lastStatus=RUNNING taskDefinition="ECS-WORDPRESS" INFO[0007] Stopped container... container=2ea5175d-e957-467e-8fd1-4b66d2a4a9c3/wordpress desiredStatus=STOPPED lastStatus=STOPPED taskDefinition="ECS-WORDPRESS" INFO[0007] Stopped container... container=2ea5175d-e957-467e-8fd1-4b66d2a4a9c3/mysql desiredStatus=STOPPED lastStatus=STOPPED taskDefinition="ECS-WORDPRESS"
To run tasks as an ECS service:
$ ecs-cli compose service up --cluster wordpress --cluster-config wordpress INFO[0001] Using ECS task definition TaskDefinition="ECS-WORDPRESS:10" INFO[0001] Created an ECS service service=ECS-WORDPRESS taskDefinition="ECS-WORDPRESS:10" INFO[0001] Updated ECS service successfully desiredCount=1 force-deployment=false service=ECS-WORDPRESS INFO[0017] (service ECS-WORDPRESS) has started 1 tasks: (task 860a2438-ee98-4a39-8898-4af1ca7c24c6). timestamp="2018-12-22 20:11:07 +0000 UTC" INFO[0033] Service status desiredCount=1 runningCount=1 serviceName=ECS-WORDPRESS INFO[0033] ECS Service has reached a stable state desiredCount=1 runningCount=1 serviceName=ECS-WORDPRESS
We can see a service is up and running:
Now, we can scale the tasks via service. So, to scale in the task to 0, we use the following:
$ ecs-cli compose service scale 0 --cluster wordpress --cluster-config wordpress
To keep the scale as 1, we need to down the service, and modify the memory_limit in ecs-params.yml. Then, up the service again.
$ ecs-cli compose service down --cluster wordpress --cluster-config wordpress INFO[0000] Updated ECS service successfully desiredCount=0 force-deployment=false service=ECS-WORDPRESS INFO[0001] Service status desiredCount=0 runningCount=1 serviceName=ECS-WORDPRESS INFO[0032] Service status desiredCount=0 runningCount=0 serviceName=ECS-WORDPRESS INFO[0032] (service ECS-WORDPRESS) has stopped 1 running tasks: (task a8772c92-bc5a-4ffa-8d87-802a63facd8e). timestamp="2018-12-22 20:41:55 +0000 UTC" INFO[0032] ECS Service has reached a stable state desiredCount=0 runningCount=0 serviceName=ECS-WORDPRESS INFO[0032] Deleted ECS service service=ECS-WORDPRESS INFO[0032] ECS Service has reached a stable state desiredCount=0 runningCount=0 serviceName=ECS-WORDPRESS
$ ecs-cli compose service up --cluster wordpress --cluster-config wordpress INFO[0001] Using ECS task definition TaskDefinition="ECS-WORDPRESS:11" INFO[0001] Created an ECS service service=ECS-WORDPRESS taskDefinition="ECS-WORDPRESS:11" INFO[0001] Updated ECS service successfully desiredCount=1 force-deployment=false service=ECS-WORDPRESS INFO[0017] Service status desiredCount=1 runningCount=1 serviceName=ECS-WORDPRESS INFO[0017] (service ECS-WORDPRESS) has started 1 tasks: (task cf58034b-6b26-44b4-aa00-f9522c71ef33). timestamp="2018-12-22 20:45:15 +0000 UTC" INFO[0017] ECS Service has reached a stable state desiredCount=1 runningCount=1 serviceName=ECS-WORDPRESS
We don't have to set service scale to 1 because it's the default:
ecs-cli compose service scale 1 --cluster wordpress --cluster-config wordpress
When we are done with this tutorial, we should clean up our resources so they do not incur any more charges. First, delete the service so that it stops the existing containers and does not try to run any more tasks.
Now, take down our cluster, which cleans up the resources that we created earlier with ecs-cli up:
$ ecs-cli down --cluster wordpress Are you sure you want to delete your cluster? [y/N] y INFO[0003] Waiting for your cluster resources to be deleted... INFO[0004] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS INFO[0065] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS INFO[0132] Cloudformation stack status stackStatus=DELETE_IN_PROGRESS INFO[0193] Deleted cluster cluster=wordpress
The command deleted the cloudformation with resources created and the cluster including our ecs instance.
Docker & K8s
- Docker install on Amazon Linux AMI
- Docker install on EC2 Ubuntu 14.04
- Docker container vs Virtual Machine
- Docker install on Ubuntu 14.04
- Docker Hello World Application
- Nginx image - share/copy files, Dockerfile
- Working with Docker images : brief introduction
- Docker image and container via docker commands (search, pull, run, ps, restart, attach, and rm)
- More on docker run command (docker run -it, docker run --rm, etc.)
- Docker Networks - Bridge Driver Network
- Docker Persistent Storage
- File sharing between host and container (docker run -d -p -v)
- Linking containers and volume for datastore
- Dockerfile - Build Docker images automatically I - FROM, MAINTAINER, and build context
- Dockerfile - Build Docker images automatically II - revisiting FROM, MAINTAINER, build context, and caching
- Dockerfile - Build Docker images automatically III - RUN
- Dockerfile - Build Docker images automatically IV - CMD
- Dockerfile - Build Docker images automatically V - WORKDIR, ENV, ADD, and ENTRYPOINT
- Docker - Apache Tomcat
- Docker - NodeJS
- Docker - NodeJS with hostname
- Docker Compose - NodeJS with MongoDB
- Docker - Prometheus and Grafana with Docker-compose
- Docker - StatsD/Graphite/Grafana
- Docker - Deploying a Java EE JBoss/WildFly Application on AWS Elastic Beanstalk Using Docker Containers
- Docker : NodeJS with GCP Kubernetes Engine
- Docker : Jenkins Multibranch Pipeline with Jenkinsfile and Github
- Docker : Jenkins Master and Slave
- Docker - ELK : ElasticSearch, Logstash, and Kibana
- Docker - ELK 7.6 : Elasticsearch on Centos 7
- Docker - ELK 7.6 : Filebeat on Centos 7
- Docker - ELK 7.6 : Logstash on Centos 7
- Docker - ELK 7.6 : Kibana on Centos 7
- Docker - ELK 7.6 : Elastic Stack with Docker Compose
- Docker - Deploy Elastic Cloud on Kubernetes (ECK) via Elasticsearch operator on minikube
- Docker - Deploy Elastic Stack via Helm on minikube
- Docker Compose - A gentle introduction with WordPress
- Docker Compose - MySQL
- MEAN Stack app on Docker containers : micro services
- MEAN Stack app on Docker containers : micro services via docker-compose
- Docker Compose - Hashicorp's Vault and Consul Part A (install vault, unsealing, static secrets, and policies)
- Docker Compose - Hashicorp's Vault and Consul Part B (EaaS, dynamic secrets, leases, and revocation)
- Docker Compose - Hashicorp's Vault and Consul Part C (Consul)
- Docker Compose with two containers - Flask REST API service container and an Apache server container
- Docker compose : Nginx reverse proxy with multiple containers
- Docker & Kubernetes : Envoy - Getting started
- Docker & Kubernetes : Envoy - Front Proxy
- Docker & Kubernetes : Ambassador - Envoy API Gateway on Kubernetes
- Docker Packer
- Docker Cheat Sheet
- Docker Q & A #1
- Kubernetes Q & A - Part I
- Kubernetes Q & A - Part II
- Docker - Run a React app in a docker
- Docker - Run a React app in a docker II (snapshot app with nginx)
- Docker - NodeJS and MySQL app with React in a docker
- Docker - Step by Step NodeJS and MySQL app with React - I
- Installing LAMP via puppet on Docker
- Docker install via Puppet
- Nginx Docker install via Ansible
- Apache Hadoop CDH 5.8 Install with QuickStarts Docker
- Docker - Deploying Flask app to ECS
- Docker Compose - Deploying WordPress to AWS
- Docker - WordPress Deploy to ECS with Docker-Compose (ECS-CLI EC2 type)
- Docker - WordPress Deploy to ECS with Docker-Compose (ECS-CLI Fargate type)
- Docker - ECS Fargate
- Docker - AWS ECS service discovery with Flask and Redis
- Docker & Kubernetes : minikube
- Docker & Kubernetes 2 : minikube Django with Postgres - persistent volume
- Docker & Kubernetes 3 : minikube Django with Redis and Celery
- Docker & Kubernetes 4 : Django with RDS via AWS Kops
- Docker & Kubernetes : Kops on AWS
- Docker & Kubernetes : Ingress controller on AWS with Kops
- Docker & Kubernetes : HashiCorp's Vault and Consul on minikube
- Docker & Kubernetes : HashiCorp's Vault and Consul - Auto-unseal using Transit Secrets Engine
- Docker & Kubernetes : Persistent Volumes & Persistent Volumes Claims - hostPath and annotations
- Docker & Kubernetes : Persistent Volumes - Dynamic volume provisioning
- Docker & Kubernetes : DaemonSet
- Docker & Kubernetes : Secrets
- Docker & Kubernetes : kubectl command
- Docker & Kubernetes : Assign a Kubernetes Pod to a particular node in a Kubernetes cluster
- Docker & Kubernetes : Configure a Pod to Use a ConfigMap
- AWS : EKS (Elastic Container Service for Kubernetes)
- Docker & Kubernetes : Run a React app in a minikube
- Docker & Kubernetes : Minikube install on AWS EC2
- Docker & Kubernetes : Cassandra with a StatefulSet
- Docker & Kubernetes : Terraform and AWS EKS
- Docker & Kubernetes : Pods and Service definitions
- Docker & Kubernetes : Service IP and the Service Type
- Docker & Kubernetes : Kubernetes DNS with Pods and Services
- Docker & Kubernetes : Headless service and discovering pods
- Docker & Kubernetes : Scaling and Updating application
- Docker & Kubernetes : Horizontal pod autoscaler on minikubes
- Docker & Kubernetes : From a monolithic app to micro services on GCP Kubernetes
- Docker & Kubernetes : Rolling updates
- Docker & Kubernetes : Deployments to GKE (Rolling update, Canary and Blue-green deployments)
- Docker & Kubernetes : Slack Chat Bot with NodeJS on GCP Kubernetes
- Docker & Kubernetes : Continuous Delivery with Jenkins Multibranch Pipeline for Dev, Canary, and Production Environments on GCP Kubernetes
- Docker & Kubernetes : NodePort vs LoadBalancer vs Ingress
- Docker & Kubernetes : MongoDB / MongoExpress on Minikube
- Docker & Kubernetes : Load Testing with Locust on GCP Kubernetes
- Docker & Kubernetes : MongoDB with StatefulSets on GCP Kubernetes Engine
- Docker & Kubernetes : Nginx Ingress Controller on Minikube
- Docker & Kubernetes : Setting up Ingress with NGINX Controller on Minikube (Mac)
- Docker & Kubernetes : Nginx Ingress Controller for Dashboard service on Minikube
- Docker & Kubernetes : Nginx Ingress Controller on GCP Kubernetes
- Docker & Kubernetes : Kubernetes Ingress with AWS ALB Ingress Controller in EKS
- Docker & Kubernetes : Setting up a private cluster on GCP Kubernetes
- Docker & Kubernetes : Kubernetes Namespaces (default, kube-public, kube-system) and switching namespaces (kubens)
- Docker & Kubernetes : StatefulSets on minikube
- Docker & Kubernetes : RBAC
- Docker & Kubernetes Service Account, RBAC, and IAM
- Docker & Kubernetes - Kubernetes Service Account, RBAC, IAM with EKS ALB, Part 1
- Docker & Kubernetes : Helm Chart
- Docker & Kubernetes : My first Helm deploy
- Docker & Kubernetes : Readiness and Liveness Probes
- Docker & Kubernetes : Helm chart repository with Github pages
- Docker & Kubernetes : Deploying WordPress and MariaDB with Ingress to Minikube using Helm Chart
- Docker & Kubernetes : Deploying WordPress and MariaDB to AWS using Helm 2 Chart
- Docker & Kubernetes : Deploying WordPress and MariaDB to AWS using Helm 3 Chart
- Docker & Kubernetes : Helm Chart for Node/Express and MySQL with Ingress
- Docker & Kubernetes : Deploy Prometheus and Grafana using Helm and Prometheus Operator - Monitoring Kubernetes node resources out of the box
- Docker & Kubernetes : Deploy Prometheus and Grafana using kube-prometheus-stack Helm Chart
- Docker & Kubernetes : Istio (service mesh) sidecar proxy on GCP Kubernetes
- Docker & Kubernetes : Istio on EKS
- Docker & Kubernetes : Istio on Minikube with AWS EC2 for Bookinfo Application
- Docker & Kubernetes : Deploying .NET Core app to Kubernetes Engine and configuring its traffic managed by Istio (Part I)
- Docker & Kubernetes : Deploying .NET Core app to Kubernetes Engine and configuring its traffic managed by Istio (Part II - Prometheus, Grafana, pin a service, split traffic, and inject faults)
- Docker & Kubernetes : Helm Package Manager with MySQL on GCP Kubernetes Engine
- Docker & Kubernetes : Deploying Memcached on Kubernetes Engine
- Docker & Kubernetes : EKS Control Plane (API server) Metrics with Prometheus
- Docker & Kubernetes : Spinnaker on EKS with Halyard
- Docker & Kubernetes : Continuous Delivery Pipelines with Spinnaker and Kubernetes Engine
- Docker & Kubernetes : Multi-node Local Kubernetes cluster : Kubeadm-dind (docker-in-docker)
- Docker & Kubernetes : Multi-node Local Kubernetes cluster : Kubeadm-kind (k8s-in-docker)
- Docker & Kubernetes : nodeSelector, nodeAffinity, taints/tolerations, pod affinity and anti-affinity - Assigning Pods to Nodes
- Docker & Kubernetes : Jenkins-X on EKS
- Docker & Kubernetes : ArgoCD App of Apps with Heml on Kubernetes
- Docker & Kubernetes : ArgoCD on Kubernetes cluster
- Docker & Kubernetes : GitOps with ArgoCD for Continuous Delivery to Kubernetes clusters (minikube) - guestbook
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization