Nothing Special   »   [go: up one dir, main page]

Getting Started With Containers in Azure Deploy Secure Cloud Applications Using Terraform 2Nd Edition Shimon Ifrah 2 Full Chapter

Download as pdf or txt
Download as pdf or txt
You are on page 1of 68

Getting Started with Containers in

Azure: Deploy Secure Cloud


Applications Using Terraform 2nd
Edition Shimon Ifrah
Visit to download the full and correct content document:
https://ebookmass.com/product/getting-started-with-containers-in-azure-deploy-secur
e-cloud-applications-using-terraform-2nd-edition-shimon-ifrah-2/
Shimon Ifrah

Getting Started with Containers in


Azure
Deploy Secure Cloud Applications Using Terraform
2nd ed.
Shimon Ifrah
Melbourne, VIC, Australia

ISBN 978-1-4842-9971-5 e-ISBN 978-1-4842-9972-2


https://doi.org/10.1007/978-1-4842-9972-2

© Shimon Ifrah 2020, 2024

This work is subject to copyright. All rights are solely and exclusively
licensed by the Publisher, whether the whole or part of the material is
concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in
any other physical way, and transmission or information storage and
retrieval, electronic adaptation, computer software, or by similar or
dissimilar methodology now known or hereafter developed.

The use of general descriptive names, registered names, trademarks,


service marks, etc. in this publication does not imply, even in the
absence of a specific statement, that such names are exempt from the
relevant protective laws and regulations and therefore free for general
use.

The publisher, the authors, and the editors are safe to assume that the
advice and information in this book are believed to be true and accurate
at the date of publication. Neither the publisher nor the authors or the
editors give a warranty, expressed or implied, with respect to the
material contained herein or for any errors or omissions that may have
been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.

This Apress imprint is published by the registered company APress


Media, LLC, part of Springer Nature.
The registered company address is: 1 New York Plaza, New York, NY
10004, U.S.A.
Any source code or other supplementary material referenced by the
author in this book is available to readers on GitHub
(https://github.com/Apress/Getting-Started-with-Containers-in-
Azure). For more detailed information, please visit
https://www.apress.com/gp/services/source-code.
Table of Contents
Chapter 1:​Getting Started with Azure and Terraform
Introduction
Goals of This Chapter
Tools and Services for the Setup
Visual Studio Code
VS Code Extensions
Windows Subsystem for Linux
Azure CLI
PowerShell 7
Terraform
A High-Level Example of Terraform
Installing Terraform on macOS
Enabling Terraform Tab Completion on macOS
Installing Terraform on Linux
Installing Terraform on Ubuntu
Enabling Terraform Tab Completion on Ubuntu
Installing Terraform on Windows
Terraform Package Manager
How to Use tfenv
Getting Started with Azure Infrastructure
Authenticating to Azure
Deploying Azure Infrastructure with Terraform
Summary
Chapter 2:​Azure Web App for Containers
Introduction
Setting Up Web App for Containers
Provider Configuration
Web App for Containers Configuration
The “Terraform Plan” Command
Deploying Web App for Containers
Deploying the Code
Terraform Output
Using a Git Ignore File with Terraform
Cleaning Up Our Deployment
Managing Web App for Containers
Scaling
Backing Up Web Apps
Customizing Deployment
Securing Web App for Containers
HTTPS
Private Endpoints
Disabling Public Access to the Web App
Summary
Chapter 3:​Azure Container Registry
Introduction
Key Features of Azure Container Images
Setting Up the Azure Container Registry
Terraform Configuration
Deploying the Azure Container Registry
Adding Tags
Noticing the Output
Building, Pushing, and Running Container Images with ASR
Tasks
Pulling an Image from ACR
ACR Pricing Tiers
Managing the Azure Container Registry
ACR Tasks
Running Azure CLI Commands with Terraform
Terraform Null Resource
Securing ACR
Terraform Data Sources
Securing Our ACR Configuration
Using ACR with Azure Web App for Containers
Using a Terraform Variables File
Configuring Azure Web App with ACR
Passing Variables Using “Terraform Apply”
Checking the Logs
Summary
Chapter 4:​Azure Container Instances
Introduction
Key Benefits of ACI
Use Cases
Deploying Azure Container Instances
Full Code
Deploying Multiple ACI Containers
Using Azure Container Instances with Azure Container Registry
The “Variables.​tf” File
The “Main.​tf” File
Applying the Code
Mounting a Data Volume to an ACI Container
Storage Account
Azure File Share
Mounting Data Volume to the Container
The Complete Code
Managing Azure Container Instances
Connecting to a Running ACI Container
Using Azure CLI to Run Commands inside ACI
Viewing ACI Logs
Using Azure CLI to View Logs
Viewing Diagnostic Information
Enabling Advanced Log Collection
Configuring Azure Log Analytics
Viewing the Logs
Stopping, Starting, and Restarting ACI Containers with Azure
CLI
Stopping the Container Group
Starting the Container Group
Restarting the Container Group
Liveness and Readiness Probes
Liveness Probes
Readiness Probe
Summary
Chapter 5:​Azure Kubernetes Service
Introduction
About Kubernetes
Kubernetes Components
Getting Started with AKS
Deploying the AKS Cluster
Connecting to AKS Using the Azure Command-Line Interface
Deploying an Application to the AKS Cluster
Scaling the Application
Connecting the AKS Cluster to the Azure Container Registry
Using the ACR Container Image with AKS
AKS Volumes
Creating a Storage Class
Creating a Volume Claim
Configuring a Pod to Use a Persistent Volume
Upgrading an AKS Cluster
Autoupgrading the AKS Cluster
Terraform Remote State
Configuring the Remote State
Adding Backend Configuration
State Locking
Exporting Azure Resources to Terraform
Summary
Chapter 6:​Azure DevOps and Container Service
Introduction
Azure DevOps Services
Setting Up Azure DevOps
Creating an Azure DevOps Organization
Creating a Project
Creating a Personal Access Token
Creating a Repository
Using Terraform with Azure DevOps
Installing Terraform Task
Azure Pipelines
Creating an Azure Container Registry
Creating an Azure Pipeline
Reviewing the Pipeline
Building and Pushing a Docker Image to ACR with Azure
Pipelines
Using Terraform Destroy with Azure Pipelines
The AzAPI Provider
Deploying an ACR Using the AzAPI Provider
Full Code
Managing Secrets in Azure Key Vault and Azure DevOps
Deploying Azure Key Vault Using Terraform
Creating a Secret in Azure Key Vault
Connecting Azure Key Vault to Azure Pipelines
Accessing Key Vault Secrets from a YAML Pipeline
Accessing Secrets from an Azure Pipeline
Summary
Chapter 7:​Azure Compliance and Security
Introduction
Defender for Cloud
Setting Up Azure with Defender for Containers
Checking the Deployment
Securing IaC Code with Defender for DevOps
Installing Extensions
Connecting the Azure DevOps Organization to Defender for
DevOps
Enabling the Plan
Scanning a Terraform Pipeline for Vulnerabilities
Summary
Index
About the Author
Shimon Ifrah
is a solution architect, writer, tech
blogger, and author with over 15 years of
experience in the design, management,
and deployment of information
technology systems, applications, and
networks. In the last decade, Shimon has
specialized in cloud computing and
containerized applications for Microsoft
Azure, Microsoft 365, Azure DevOps, and
.NET. Shimon also holds over 20 vendor
certificates from Microsoft, Amazon Web
Services, VMware, Oracle, and Cisco.
During his career in the IT industry, he
has worked for some of the world’s largest managed services and
technology companies, assisting them in designing and managing
systems used by millions of people every day. He is based in Melbourne,
Australia.
About the Technical Reviewer
Kasam Shaikh
is a prominent figure in India’s artificial
intelligence landscape, holding the
distinction of being one of the country’s
first four Microsoft MVPs in AI. Currently
serving as a senior architect at
Capgemini, Kasam boasts an impressive
track record as an author, having
authored five best-selling books focused
on Azure and AI technologies. Beyond
his writing endeavors, Kasam is
recognized as a Microsoft certified
trainer and influential tech YouTuber
(@mekasamshaikh). He also leads the
largest online Azure AI community,
known as DearAzure—Azure INDIA and
is a globally renowned AI speaker. His
commitment to knowledge sharing extends to his contributions to
Microsoft Learn, where he plays a pivotal role.
Within the realm of AI, Kasam is a respected subject matter expert
in Generative AI for the Cloud, complementing his role as a senior cloud
architect. He actively promotes the adoption of no-code and Azure
OpenAI solutions and possesses a strong foundation in hybrid and
cross-cloud practices. Kasam’s versatility and expertise make him an
invaluable asset in the rapidly evolving landscape of technology,
contributing significantly to the advancement of Azure and AI.
In summary, Kasam Shaikh is a multifaceted professional who excels
in both his technical expertise and knowledge dissemination. His
contributions span writing, training, community leadership, public
speaking, and architecture, establishing him as a true luminary in the
world of Azure and AI.
© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2024
S. Ifrah, Getting Started with Containers in Azure
https://doi.org/10.1007/978-1-4842-9972-2_1

1. Getting Started with Azure and Terraform


Shimon Ifrah1
(1) Melbourne, VIC, Australia

Introduction
Welcome to the first chapter of Deploy Containers on Azure Using Terraform. Since the release of the first
edition of this book, many things have changed, and so I decided to do a complete rewrite of the original
book and introduce the Terraform software and explain how it can help you simplify your deployments on
Azure and, more important, how it can deploy fast and always produce the same results.
The focus of this book will be on how to use Terraform to deploy container services, infrastructure
services, and other services on Azure using infrastructure as code (IaC).
Terraform is an open-source IaC tool developed by HashiCorp in order to simplify deployments of cloud
infrastructure using descriptive code language.
Once the code is deployed to Azure, it can also be version controlled and shared for development
purposes.
This chapter will focus on how to get started setting up your development environment to use Terraform
and connect to Azure and on deploying a sample resource.
Based on the assumption that you already have a working knowledge of Terraform and Azure, this book
will focus on teaching the fundamentals of these technologies.
To deploy resources to Azure using Terraform, there are a few tools I would recommend using to make
your deployment journey smoother and easier.
If you already have a preferred working setup and have the latest version of Terraform and Azure
command-line interface (CLI) installed and up and running, you don’t have to use the setup outlined in this
book, or the book recommended here.

Goals of This Chapter


The objectives of this chapter are to:
install all the required tools and services of Terraform
understand at a high level what configuring Terraform does
authenticate to Azure using Azure CLI
deploy an Azure resource group using Terraform

Tools and Services for the Setup


In the following sections, we will go over the tools and services needed to deploy infrastructure to Azure
using Terraform. These resources can be run on Windows, macOS, and Linux operating systems.
The following tools and services are recommended:
Visual Studio Code
Visual Studio Code extensions
Windows Subsystem for Linux (recommended but not essential)
Azure command-line interface
PowerShell 7
Azure PowerShell Module
Terraform

Visual Studio Code


Visual Studio Code (VS Code) is a lightweight source code editor developed by Microsoft that is free to
download. It supports a wide range of programming languages and frameworks, including .NET, Python,
Java, Node, PHP, HTML, and many more.
VS Code is currently one of the most popular source code editors because of the wide range of extensions
it of offers to allow developers to write extensions that extend the functionality of the editor. In this book, we
will use the Terraform extension.

Installing VS Code
VS Code is available for the Windows, macOS, and Linux operating systems. You can download all of these
versions from the following URL: https://code.visualstudio.com/download.
Once you download the correct version for your system, go ahead and install it.

VS Code Extensions
VS Code extensions are core components that allow software and infrastructure developers to work smarter
by complementing their capabilities with new features, functionality, and integrations.
Currently, the VS Code extensions library contains thousands of extensions that developers can use to
produce cleaner and better code.
In this book, we will use a few extensions to produce code and infrastructure in Azure.

Installing VS Code Extensions


To install extensions in VS Code, take the following steps:
1. Open VS Code.

2. Click the “Extensions” icon, as shown in Figure 1-1.


Figure 1-1 The VS Code “Extensions” icon
To get the most out of this book and Terraform, what follows are a few VS Code extensions I would
recommend installing that will help you become a great infrastructure developer.
Azure Terraform: The official Microsoft VS Code extension for Terraform offers IntelliSense, linting,
autocomplete, and ARM template support for Terraform configuration.

Figure 1-2 The Azure Terraform VS Code extension

HashiCorp Terraform: HashiCorp, the company behind Terraform, has its own official VS Code extension
that offers IntelliSense, syntax validation, syntax highlighting, code navigation, code formatting, code
snippets, a Terraform module explorer, and Terraform commands.

Figure 1-3 The HashiCorp Terraform VS Code extension

Azure Account: Another official Microsoft extension, Azure Account simplifies the connectivity process
between VS Code and Azure. It allows developers to connect to multiple Azure subscriptions and manage
Azure resources.
Figure 1-4 The Azure Account VS Code extension

PowerShell: Microsoft’s PowerShell VS Code extension offers support for PowerShell within VS Code and
allows writing and debugging PowerShell scripts. The extension also offers the classic PowerShell
Integrated Scripting Environment theme.

Figure 1-5 The PowerShell VS Code extension

Linter: This extension offers linting capabilities that analyze and check the code written for errors and
bugs. It also offers linting capabilities for YAML files used by Kubernetes code deployments.
To lint YAML Ain’t Markup Language, or YAML, files, make sure you install the YAMLint package for
macOS or Linux.
Figure 1-6 The Linter VS Code extension

The extensions just described will help you get started using Azure and Terraform very quickly. Make sure
you have all of them installed.

Windows Subsystem for Linux


If you’re planning on using a Windows operating system to deploy resources to Azure using Terraform, I
recommend you go with Windows Subsystem for Linux (WSL) if you have enough Linux Shell skills.
WSL allows us to run Linux distributions natively on Windows 11 and Windows Server. It provides a
convenient development environment for DevOps and Terraform specifically because of its:
seamless integration with the Windows operating system, allowing us to use all the native Linux tools and
scripts without using a different system
native command-line experience, giving us access to Linux packages and utilities
access to DevOps tools that are available on Linux only
By using WSL, developers and engineers can benefit from the strength of both operating systems and
utilize all the tools and services they offer under a single system.

Installing WSL on Windows 11


Since the release of WSL back in 2016, the installation process has been simplified tenfold; now, installing
WSL is just a matter of running a single command.
To install WSL on a Windows 11 computer, open PowerShell or a Windows Command terminal as an
administrator and run the following command:

wsl–install

This command will install and enable all the features that make WSL work on your computer and install
the Ubuntu distribution of Linux, which is the default, but you can change it.
If you’re using macOS or Linux, there is no need to change anything, as all the tools that we will use are
natively available on both operating systems.

Azure CLI
The next tool that we need to install is the Azure CLI command-line interface, which will allow us to manage
Azure using commands. Azure CLI is a cross-platform tool that is available on all operating systems.

Installing Azure CLI on Windows with WinGet


To install Azure CLI on a computer running Windows 11, open PowerShell in administrator mode and run
the following command:

winget install -e --id Microsoft.AzureCLI

This command uses WinGet, which is Windows’s package manager that allows us to install tools and
applications directly from the command line.

Installing Azure CLI on Linux


To install Azure CLI on a computer running Linux, visit the following page and select the Linux distribution
you’re running:
https://learn.microsoft.com/en-us/cli/azure/install-azure-cli
If you’re using Ubuntu Linux, you can install Azure CLI using the following single command:

curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Installing Azure CLI on macOS


To install Azure CLI on a macOS using Homebrew, run the following command from the macOS terminal:

brew update && brew install azure-cli

PowerShell 7
Microsoft PowerShell is a cross-platform command-line utility that allows us to automate tasks using
commands and scripts, and it is available on Windows, Linux, and macOS.
With PowerShell, we can install the Azure PowerShell module and manage Azure resources directly from
the command line using cmdlets or scripts.
The main selling point of PowerShell 7 is its cross-platform support, which contributed to the program’s
success and widened its limited exposure, previously being available for Windows environments only.
PowerShell 7 can be installed on all platforms using different methods. For the sake of simplicity, I will
just go over one method for each platform. For more information about the installation options, visit
PowerShell’s official website at https://github.com/PowerShell/PowerShell.

Installing PowerShell 7 on Windows


The recommended way to install PowerShell 7 on a Windows computer is to use the Windows Package
Manager WinGet command-line tool. WinGet allows us to install, upgrade, and remove applications and tools
like PowerShell directly from the command line and comes preinstalled on Windows 11 and recent versions
of Windows 10.
To install PowerShell 7, open a Windows command terminal or PowerShell 5.1, which is also installed on
Windows 10 and 11 by default, and run the following cmdlet:

winget install --id Microsoft.Powershell --source winget

To install the preview edition of PowerShell, run this command:

winget install --id Microsoft.Powershell.Preview --source winget

If you already have PowerShell 7 installed on your computer and would like to update it to the latest
version, run the following command to check for updates:

winget update

To update all applications using WinGet, run the next command:

winget update –all

To update only PowerShell, you can run:


winget update Microsoft.PowerShell
Note that in some cases, you might need to uninstall PowerShell 7 before installing a new version with
WinGet. To uninstall PowerShell 7, run the following cmdlet:

winget uninstall Microsoft.PowerShell

Once the previous version is uninstalled, install PowerShell 7 with the command that follows:

winget install Microsoft.PowerShell

Installing PowerShell 7 on macOS


The recommended way to install PowerShell 7 on macOS is by using Homebrew, which is a package manager
for macOS. Like WinGet, Homebrew takes care of the installation process and allows us to install, update,
and remove applications.
If you need to install Homebrew, open the Terminal application on your macOS and run the following
command:

/bin/bash -c "$(curl -fsSL


https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

After the Homebrew installation is completed, close and reopen the Terminal and run the following
command to install PowerShell 7:

brew install --cask powershell

Once PowerShell 7 is installed, you can start using it by typing “pwsh.” The pwsh command starts
PowerShell and allows you to run PowerShell cmdlets or scripts.
To update all applications, including PowerShell, on macOS, run the following command:

brew update

After the command is finished, run the following command to start the update process:

brew upgrade

When the Homebrew update is completed, it will display a summary report of the updated packages,
including PowerShell 7.

Installing PowerShell 7 on Linux


PowerShell can be installed on almost all Linux distributions. Here, I will show how to install it on Ubuntu
22.04.
To install PowerShell, run the following commands from a bash terminal:

sudo apt-get update

sudo apt-get install -y wget apt-transport-https software-properties-common

wget -q
"https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-
microsoft-prod.deb"

sudo dpkg -i packages-microsoft-prod.deb

rm packages-microsoft-prod.deb
packages.microsoft.com

sudo apt-get update


sudo apt-get install -y powershell
Once the installation is complete, you can start PowerShell by using the following command: pwsh. From
this point forward, all PowerShell cmdlets will be the same on all operating systems.

Terraform
Now that we have all the tools we need to get started using Microsoft Azure and DevOps, it’s time to install
Terraform and begin the process.
Terraform is the most popular and widely used IaC software development tool available on the market
and is considered an industry standard for infrastructure deployment.
It’s also the oldest tool for infrastructure deployment and has been around for many years. Terraform
supports most major cloud providers, like AWS, or Amazon Web Services, and GCP, or Google Cloud
Platform.
Terraform uses the concept of domain-specific language, also known as HashiCorp Configuration
Language. The idea behind the language is to use a declarative approach to infrastructure code.
In the declarative approach, we define the desired state of the infrastructure and let Terraform handle
the deployment and configuration.

A High-Level Example of Terraform


The following is an example of code we can use to create an Azure Resource Group using Terraform:

# main.tf
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "example" {


name = "Apress-ch01"
location = "West Europe"
}

In this example, we have a Terraform configuration file called main.tf.


It is important to note that all Terraform configuration files need to use the .TF file extension in order to
be deployed by Terraform.
In Terraform, a provider has all the domain-specific code to deploy resources to a cloud provider like
Azure. Each cloud provider has its own Terraform provider. The Azure Terraform provider is called Azure
Resource Manager (Azure RM).
The following code declares that we are using the Microsoft Azure Terraform provider.

provider "azurerm" {
features {}
}

Next, we will tell Terraform to create a resource group in the Azure Web Europe data center. The name of
the resource group will be Apress-ch01. Once we run the code, Terraform will go ahead and deploy the
resource group.
We will go over the process for setting up and deploying a resource shortly. The previous code is just
meant to serve as a high-level example of how Terraform deploys infrastructure
Now that we have learned a bit about Terraform, let’s take a look at how to install it. Terraform is
available for Linux, macOS, and Windows systems. My recommendation would be to use Terraform on Linux,
macOS, or WSL. Because many DevOps tools are available natively on Linux and macOS, using Windows
won’t produce the best development results.

Installing Terraform on macOS


The method I would recommend to install Terraform on a macOS is to use a package manager; in our case, it
is best to use Brew.
To install Terraform using Brew, you can use the next couple of commands on your macOS terminal.
First, install the HashiCorp repository using the tap command: brew tap hashicorp/tap. Then, to
install Terraform, run this command:

brew install hashicorp/tap/terraform.

If you already have Terraform installed and want to update it to the latest version, you can take the
following steps.
First, update Brew using the update command: brew update. Once Brew is updated, run this
command: brew upgrade hashicorp/tap/terraform.
Now Terraform is ready to go. To check which version of Terraform is installed on your machine, run
terraform -version.

Enabling Terraform Tab Completion on macOS


To enable tab completion for Terraform, first make sure you have the Bash profile configured by running the
following command: Touch ~/bashrc. Then, run this command:

terraform -install-autocomplete.

Installing Terraform on Linux


In this section, I will install Terraform only on Ubuntu; if you’re running a different Linux distribution, you
can go to the following URL to get the version you need:
https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-
cli.
Terraform is available for the following Linux distributions:
CentOS/RHEL
Fedora
Amazon Linux

Installing Terraform on Ubuntu


To install Terraform on Ubuntu, we first need to install the HashiCorp package repository, which we can do
here:

wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o


/usr/share/keyrings/hashicorp-archive-keyring.gpg

Then we need to install the GPG security signature using the following command:

echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]


https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee
/etc/apt/sources.list.d/hashicorp.list

The last command will install Terraform:

sudo apt update && sudo apt install terraform

Enabling Terraform Tab Completion on Ubuntu


To enable tab completion for Terraform on Linux Ubuntu, first make sure you have the Bash profile
configured by running the following command:

Touch ~/bashrc

Then, run this command:


terraform -install-autocomplete

Installing Terraform on Windows


The recommended method for installing Terraform on Windows is to use a package manager, and to do this
we will again use WinGet.
To search for Terraform with WinGet, open a PowerShell terminal and run the following command:

winget search terraform

The output from the command is shown in the following. The version of Terraform we’re looking for is
1.5.3.

Name Id Version Match Source


--------------------------------------------------------------------------
Hashicorp Terraform Hashicorp.Terraform 1.5.3 winget

Note When the ID of the app shows “Vendor. AppName,” it means that app is the official application.

To install Terraform, run this command:

Winget install Hashicorp.Terraform

Terraform Package Manager


Before we move on with, there is a tool I recommend you use to manage Terraform. This tool is optional but
can help in managing Terraform across multiple deployments.

Note Using tfenv is optional and not required to complete the labs in this book.

The tool I’m talking about is tfenv. It is a version manager for Terraform. Tfenv allows you to manage
multiple versions of Terraform on your local computer (similar to the Python virtual environment).
The tfenv process of switching between Terraform environments is simple and allows us to maintain the
compatibility of projects.
As I mentioned previously, this tool is only available on Linux and macOS; you will come across many
tools like this.

Installing tfenv on macOS


To install tfenv on macOS, we’ll use Homebrew with the brew command tool as shown in the following code:

brew install tfenv

In the next subsection, I will go over how to use tfenv.

Installing tfenv on Linux


To install tfenv on a Linux machine, use the following command, which uses Git to clone the source code of
tfenv:

git clone --depth=1 https://github.com/tfutils/tfenv.git ~/.tfenv

echo 'export PATH=$PATH:$HOME/.tfenv/bin' >> ~/.bashrc

Note Tfenv is not available in the Ubuntu package manager.

Tfenv is now installed on your computer.


How to Use tfenv
Now that we’ve tfenv installed on our computers, let’s put it to the test and use it to manage different
versions of Terraform.
To view all the available tfenv commands, run the following command:

Tfenv

The output will list all the available options, as shown in the following:

tfenv 3.0.0-18-g1ccfddb
Usage: tfenv <command> [<options>]

Commands:
install Install a specific version of Terraform
use Switch a version to use
uninstall Uninstall a specific version of Terraform
list List all installed versions
list-remote List all installable versions
version-name Print current version
init Update environment to use tfenv correctly.
pin Write the current active version to ./.terraform-version

As you can tell, using tfenv is simple, which makes it very handy for operating and managing the
Terraform versions.
Let’s start by downloading a version of Terraform by typing in the following command to view which
versions are available:

Tfenv list-remote

What follows is the output of that command (note that I am only showing 14 of the versions included in
the list):

1.6.0-alpha20230719
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc2
1.5.0-rc1
1.5.0-beta2
1.5.0-beta1
1.5.0-alpha20230504
1.5.0-alpha20230405
1.4.6
1.4.5
1.4.4

To install a specific version of Terraform, run the following command:

tfenv install 1.5.2

The command output follows. If you notice, it’s being downloaded from Terraform directly.

Installing Terraform v1.5.2


Downloading release tarball from https://releases.hashicorp.com/terraform/1.5.
##############################################################################
100.0%
Downloading SHA hash file from https://releases.hashicorp.com/terraform/1.5.2/
Downloading SHA hash signature file from https://releases.hashicorp.com/terraf
To activate a version of Terraform, first list all the installed versions with a tfenv list, as follows:

* 1.5.3 (set by /home/shimon/.tfenv/version)


1.5.2
1.3.0
1.1.8

To activate a different version of Terraform, run:

Tfenv use 1.5.2

If you check which version is active, it will show the following output:

1.5.3
* 1.5.2 (set by /home/shimon/.tfenv/version)
1.3.0
1.1.8

As I mentioned at the beginning of this section, tfenv is an optional feature and it’s not required to deploy
infrastructure. You will find that there are many handy tools available to help us be more productive and
efficient with our deployments; tfenv is just one of them.

Getting Started with Azure Infrastructure


At this stage, we have all the tools required to deploy infrastructure on Microsoft Azure. So let’s get started
and deploy something to Azure using Terraform.

Note To deploy resources to Azure, you’ll need an active Azure subscription.

Authenticating to Azure
The first step required to deploy resources to Azure is to authenticate, which we’ll do using Azure CLI
(PowerShell is not supported).
To authenticate to Azure, run the following command and click the resulting link to open the Azure
portal login:

az login --use-device-code

If you have multiple Azure subscriptions, run the following command to find the ID of the subscription to
which you’re going to deploy resources and copy the subscription ID.

az account list --output table

Using the ID you copied, run the following command to set up the subscription:

az account set subscription "SUBSCRIPTIONNAME"

We are now authenticated and ready to deploy our first Azure resource.
In this example, we are going to deploy an Azure Resource Group using Terraform with the following
code:

#1.Create_RG.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
}
}
}

provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "rg" {


name = "ApressAzureTerraform"
location = "Australia Southeast"
}

The previous code starts with a declaration of the Azure Terraform provider. The Azure terraform
provider is called azurerm.
We also have a provider features section where we can declare extra configuration items.

#1.Create_RG.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"

}
}
}

provider "azurerm" {
features {}
}

The second part of the code is the declaration of the resource group we’re going to create and deploy to
Azure.
We are deploying a resource group called ApressAzureTerraform in the Australia Southeast
data center.

resource "azurerm_resource_group" "rg" {


name = "ApressAzureTerraform"
location = "Australia Southeast"
}

Deploying Azure Infrastructure with Terraform


Now that we have a basic understanding of the code, let’s deploy the resource group to Azure.
Terraform uses the following four commands to deploy, manage, and delete resources on any platform,
not just Azure:

Terraform init
Terraform plan
Terraform apply
Terraform destroy

In the following deployment, we’ll use all of these commands as we go through the cycle of creating and
deleting resources from Azure.

The “Terraform Init” Command


We’ll start by running the terraform init command, which will initiate and download the latest version
of the Azure Terraform provider:

terraform init

Note We can specify a Terraform provider by using the version option in the required_provider section.

The output of the command is as follows:

Initializing the backend...

Initializing provider plugins...


- Finding latest version of hashicorp/azurerm...
- Installing hashicorp/azurerm v3.66.0...
- Installed hashicorp/azurerm v3.66.0 (signed by HashiCorp)

Terraform has created a lock file called .terraform.lock.hcl to record the provider selections it
made. Include this file in your version control repository so that Terraform can guarantee it makes the same
selections by default when you run "terraform init" in the future.

The “Terraform Plan” Command


Before we go ahead and deploy the code, let’s first use the Terraform plan command, which will show us
what Terraform will do without deploying the code or making any changes.
The output is shown in the following, and as you can see in the Plan line, we’ve added one resource.

Terraform used the selected providers to generate the following execution


plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# azurerm_resource_group.example will be created


+ resource "azurerm_resource_group" "example" {
+ id = (known after apply)
+ location = "australiasoutheast"
+ name = "ApressAzureTerraform"
}

Plan: 1 to add, 0 to change, 0 to destroy.

Note It is essential that you review the changes carefully, as changes made by Terraform are
irreversible.

The “Terraform Apply” Command


To deploy the resources, we’ll use the following Terraform apply command to create a resource group:

Terraform apply

Let’s now review the planned changes one more time and type “yes” to confirm.

Terraform used the selected providers to generate the following execution


plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:


# azurerm_resource_group.rg will be created
+ resource "azurerm_resource_group" "rg" {
+ id = (known after apply)
+ location = "australiasoutheast"
+ name = "ApressAzureTerraform"
}

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?


Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value:

After a little time, Terraform will display a message saying that the resources were deployed successfully.
The output of the message follows:

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The “Terraform Destroy” Command


The final step in the Terraform deployment cycle is to delete the infrastructure we just deployed, which we’ll
do with the following destroy command:

Terraform destroy

Terraform will then again display a detailed configuration message outlining the changes and their
impact on the infrastructure. It is critical that you review these changes carefully, especially when managing
live and production resources.

Terraform used the selected providers to generate the following execution


plan. Resource actions are indicated with the following symbols:
- destroy

Terraform will perform the following actions:

# azurerm_resource_group.rg will be destroyed


- resource "azurerm_resource_group" "rg" {
- id = "/subscriptions/subidremoved
/resourceGroups/ApressAzureTerraform" -> null
- location = "australiasoutheast" -> null
- name = "ApressAzureTerraform" -> null
- tags = {} -> null
}

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?


Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.

Enter a value:

If you are OK with the changes, type “yes” and Terraform will delete the resources outlined in the output
of the destroy command.

Summary
This chapter covered the basics of getting started with Terraform and installing the tools required to use it.
In the last section, we put all our learning into practice and deployed an Azure resource group using
Terraform.
© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2024
S. Ifrah, Getting Started with Containers in Azure
https://doi.org/10.1007/978-1-4842-9972-2_2

2. Azure Web App for Containers


Shimon Ifrah1
(1) Melbourne, VIC, Australia

Introduction
We’ll start this chapter by deploying services to Azure. The first service we’re going to explore and deploy is
Azure Web App for Containers. Using the knowledge we gained in Chapter 1, we will use VS Code, Azure CLI,
and Terraform.
Azure Web App for Containers is a service that is part of Azure Web Apps that allows us to deploy web or
mobile applications to Azure without the need to deploy the underlying infrastructure, like servers and
storage, allowing us to focus only on deploying our applications and let Azure manage the rest.
The platform takes Azure Web Apps to the next level by allowing us to configure applications in Docker
and ship them to Azure Web Apps but control all the runtime configuration within the application.
The service also supports Docker and other container technologies that allow us to package our
applications and dependencies into a container image.
We have the choice to use multiple programming languages with the platform like:
.NET
Java
Python
Node
The deployment process also allows us to pull our images from container registries like Azure Container
Registry (ACR) and Docker Hub or use source-code repositories like Azure Repos or GitHub.

Setting Up Web App for Containers


To get started deploying to Web App for Containers, review the Chapter 02 code in the repository for this
book.
If you look at the code, you’ll see that I have made some changes to how Terraform configuration should
be used.

Provider Configuration
To simplify things and make the code more scalable and portable, I have created the following file:
provider.tf.
The provider file contains all the details of the provider, and in our case, it’s the Azure provider. By
separating the provider configuration from the main configuration files, we centralize the provider
configuration and reduce duplication.
The content of the provider.tf is:

terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"

}
}
}
provider "azurerm" {
features {}
}

Web App for Containers Configuration


Before we deploy an app to Web App for Containers, let’s review the code and understand how it works.

Note Terraform code is called configuration.

The first block in the configuration creates a resource group. The name of the block is “rg.” Terraform doesn’t
care what you name it, but the naming does need to be consistent, and we will refer to it in the configuration.

resource "azurerm_resource_group" "rg" {


name = "ApressAzureTerraformCH02"
location = "Australia Southeast"
}

The second piece of code, detailed in the following, creates a Linux Service plan called “Linux with P1v2
plan.”

resource "azurerm_service_plan" "appservice" {


name = "Linux"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Linux"
sku_name = "P1v2"
}

These two blocks of code define the Docker image that will be used in the Web App for Containers and
the settings that are needed for it to run.

Note Later on in the book, we will create a private container register in Azure and use it for
deployments.

The last block of code, outlined in the following, creates the actual app that will be deployed to Web App for
Containers. The important parts in the configuration are in the applications_stack and the
app_settings blocks.

resource "azurerm_linux_web_app" "webapp" {


name = "ApressTFWebApp"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.appservice.id

site_config {
always_on = "true"

application_stack {
docker_image_name = "httpd:latest"
docker_registry_url = "https://index.docker.io/"

}
}
app_settings = {
"DOCKER_ENABLE_CI" = "true"
}

}
The deployment that we’re using is not overly complicated but does have all the moving parts needed to
run an application on Web App for Containers.

The “Terraform Plan” Command


Before deploying the code, it is a good idea to explore the Terraform plan command.
The job of this command is to do the following tasks:
Dependency analysis: This analyzes the Terraform configuration files and code maps all resources, data
sources, and modules that are needed for the deployment.
State analysis: The state analysis checks if an existing state file exists (terraform.tfstate) and
determine the current state of the infrastructure.
Resource Comparison: This compare the desired state defined in the configuration files with the current
state recorded in the state file (terraform.tfstate).
Execution Plan: Once the dependency, state, and resource analyses are done, Terraform will generate this
plan that outlines how the infrastructure will look and which actions need to be achieved (add, modify, or
delete).
Output: The final stage of this command is to display the execution plan and show which action will be
taken against which resources.
The purpose of the Terraform plan command is to preview the planned changes before applying
them and review their potential impact on the infrastructure.
When running a plan command, we need to navigate to the directory containing the Terraform
configuration files and issue the following command:

terraform plan

The plan command will run the previous steps against every configuration file that ends with the .tf
extension.

The Terraform State File


The Terraform state file acts as a recordkeeping mechanism for tracking the resources Terraform manages
and their current state.
The key functions of this file you need to know about are:
Mapping the file’s resources: Mapping the resources listed in the file (terraform.tfstate) and the
resources in Azure is the purpose of this file. If the configuration of Azure resources is different, Terraform
will try to “fix” it and give it the same configuration as those in the state files by deleting or removing
those resources that can be risky.
Mapping: The state file holds information about the resource type; name; provider; and attributes like
DNS, IP Address, and so on.
Locking: In a production environment, the state files should be hosted in centralized storage so that
multiple members can access them and make changes to their infrastructure without overwriting their
configuration. To prevent overwriting, Terraform can lock the state files when changes are made by a
single user. We’ll learn how to use a remote state file later on.
Remote state: By default, the state file is stored locally; however, in a production environment the best
practice is to store it in remote storage and allow collaboration.
Sensitive data: The state file should be excluded from source control storage because it contains sensitive
data like passwords, API (application programming interface) keys, and more. When using a remote state
file, the storage should be encrypted.

Deploying Web App for Containers


Now that we understand a bit more about the Terraform plan process and how the Terraform state file
works, it’s time to deploy our Web App for Containers application.
We deploy resources to Azure using the Terraform apply command. This command uses the
Terraform configuration file and creates or modifies resources in Azure. The command does exactly when
the it says it will do.
Before making any changes, Terraform will display the execution plan with the proposed changes and
will always ask for confirmation before proceeding with the changes.

Note To skip the confirmation approval step, we can use auto-approve, which will work with the “plan,”
“apply,” and “destroy” commands.

When using the Terraform apply command in a production environment, always review the execution plan
and ensure that you understand the changes Terraform will make before confirming.

Deploying the Code


To deploy our Web App for Containers app, we’ll take the following steps:
1. Open the VS Code terminal and browse the for the folder where the Terraform configuration exists.

2. Log into Microsoft Azure using the following code:

az login --use-device-code

3. If you have more than one Azure subscription, use the following command to set your subscription:

az account set --subscription "SUBSCRIPTIONID"

Note To list all your Azure subscription IDs using PowerShell, use the following command: “get-
azSubscription | Select-Object Name, subscriptionid.”

4. Run the Terraform init command to download the Azure provider.

The init command output should look like this:

Initializing the backend...

Initializing provider plugins...


- Reusing previous version of hashicorp/azurerm from the dependency lock
file
- Using previously-installed hashicorp/azurerm v3.66.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to
see
any changes that are required for your infrastructure. All Terraform
commands
should now work.

If you ever set or change modules or backend configuration for Terraform,


rerun this command to reinitialize your working directory. If you forget,
other
commands will detect it and remind you to do so if necessary.

5. The next step is to run the following plan command and review the proposed infrastructure:

Terraform plan
The output should look like this:

Terraform used the selected providers to generate the following execution


plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# azurerm_linux_web_app.webapp will be created


+ resource "azurerm_linux_web_app" "webapp" {
+ app_settings = {
+ "DOCKER_ENABLE_CI" = "true"
}
+ client_affinity_enabled = false
+ client_certificate_enabled = false
+ client_certificate_mode = "Required"
+ custom_domain_verification_id = (sensitive value)
+ default_hostname = (known after apply)
+ enabled = true
+ hosting_environment_id = (known after apply)
+ https_only = false
+ id = (known after apply)
+ key_vault_reference_identity_id = (known after apply)
+ kind = (known after apply)
+ location = "australiasoutheast"
+ name = "ApressTFWebApp"
+ outbound_ip_address_list = (known after apply)
+ outbound_ip_addresses = (known after apply)
+ possible_outbound_ip_address_list = (known after apply)
+ possible_outbound_ip_addresses = (known after apply)
+ public_network_access_enabled = true
+ resource_group_name = "ApressAzureTerraformCH02"
+ service_plan_id = (known after apply)
+ site_credential = (sensitive value)
+ zip_deploy_file = (known after apply)

+ site_config {
+ always_on = true
+ container_registry_use_managed_identity = false
+ default_documents = (known after apply)
+ detailed_error_logging_enabled = (known after apply)
+ ftps_state = "Disabled"
+ health_check_eviction_time_in_min = (known after apply)
+ http2_enabled = false
+ linux_fx_version = (known after apply)
+ load_balancing_mode = "LeastRequests"
+ local_mysql_enabled = false
+ managed_pipeline_mode = "Integrated"
+ minimum_tls_version = "1.2"
+ remote_debugging_enabled = false
+ remote_debugging_version = (known after apply)
+ scm_minimum_tls_version = "1.2"
+ scm_type = (known after apply)
+ scm_use_main_ip_restriction = false
+ use_32_bit_worker = true
+ vnet_route_all_enabled = false
+ websockets_enabled = false
+ worker_count = (known after apply)

+ application_stack {
+ docker_image_name = "httpd:latest"
+ docker_registry_password = (sensitive value)
+ docker_registry_url = "https://index.docker.io/"
+ docker_registry_username = (known after apply)
}
}
}

# azurerm_resource_group.rg will be created


+ resource "azurerm_resource_group" "rg" {
+ id = (known after apply)
+ location = "australiasoutheast"
+ name = "ApressAzureTerraformCH02"
}

# azurerm_service_plan.appservice will be created


+ resource "azurerm_service_plan" "appservice" {
+ id = (known after apply)
+ kind = (known after apply)
+ location = "australiasoutheast"
+ maximum_elastic_worker_count = (known after apply)
+ name = "Linux"
+ os_type = "Linux"
+ per_site_scaling_enabled = false
+ reserved = (known after apply)
+ resource_group_name = "ApressAzureTerraformCH02"
+ sku_name = "P1v2"
+ worker_count = (known after apply)
}

Plan: 3 to add, 0 to change, 0 to destroy.


The plan command is important and you should always take a few minutes to review the code. More
specifically, always review the last line of the output that shows the planned changes for the action.
In our case, the plan command will add the following three simple instructions: Plan: 3 to add, 0
to change, 0 to destroy. However, in existing environments, the output might show only the change
and destroy instructions; make sure you go through the list of changes and understand them before
proceeding to the apply command.
6. Next, we’ll run the following command:

terraform apply

The output of this command will be similar to that of the plan command. However, it will also include
the following output plus confirmation:

Plan: 3 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?


Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value:
I will go ahead and type “yes” here and let Terraform create the web application as per the configuration.
The Terraform application output is shown in the following code. The time it takes to create the
infrastructure depends on the number of resources in the configuration. In our case, it should take less than
a minute to complete the deployment.

azurerm_resource_group.rg: Creating...
azurerm_resource_group.rg: Creation complete after 1s
[id=/subscriptions/subid/resourceGroups/ApressAzureTerraformCH02]
azurerm_service_plan.appservice: Creating...
azurerm_service_plan.appservice: Creation complete after 7s
[id=/subscriptions/subid/resourceGroups/ApressAzureTerraformCH02/providers/Mic
azurerm_linux_web_app.webapp: Creating...
azurerm_linux_web_app.webapp: Still creating... [10s elapsed]
azurerm_linux_web_app.webapp: Still creating... [20s elapsed]
azurerm_linux_web_app.webapp: Still creating... [30s elapsed]
azurerm_linux_web_app.webapp: Creation complete after 33s
[id=/subscriptions/subid/resourceGroups/ApressAzureTerraformCH02/providers/Mic

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Now, the web app has been deployed and we can open the properties of the web app in the Azure portal
and click the URL to see it in action.
The output of the web app is shown in Figure 2-1.

Figure 2-1 Httpd default home page

In our deployment, we’re using the httpd Docker image, which runs the Apache Web Server, and it
displays the default home page.
You can find the web app URL in the Azure portal by taking the following steps:
1. Open the Azure portal using the following URL: https://portal.azure.com.

2. Open the ApressTFWebApp web app.

3. Click the “Default domain,” as shown in Figure 2-2.

Figure 2-2 Web app URL

Terraform Output
I have to say that retrieving the web app URL required a few clicks, opening a web browser, and logging into
the portal. To make our lives a bit easier, Terraform can also output the same information we retrieved from
the browser on the output screen after deploying the application.
The purpose of the output command is to display information about the deployment on our screen
without requiring us to open the portal to look for it. After all, Terraform already has all the information
about our deployment, so outputting it to the screen is simple.
The Terraform output command is very powerful and allows us to retrieve deployment values from the
Terraform state file that holds all the attributes. It also provides access to values without having to read the
state file directly.

Creating an Output File


To use the output command, I recommend that you centralize all the output commands in one file called
output.tf.
As a reminder, so far in our Web App for Containers we have the following files:

File Name Details


webapp.tf Main Web Apps for Containers configuration file
Provider.tf Azure provider configuration file
Output.tf Output configuration file

To use the output command, I have created a file called output.tf with the following configuration:

output "web_app_url" {
value = azurerm_linux_web_app.webapp.default_hostname
}

In the configuration, I declared one output value would be called web_app_url with the Azure Web
App default hostname value.
To view the hostname of the deployed web app, we can run the terraform apply command as
normal or output the value postdeployment using:

terraform output

The following output shows the web app URL we get when we run the Terraform apply command:

azurerm_resource_group.rg: Refreshing state... [id=/subscriptions/subid


/resourceGroups/ApressAzureTerraformCH02]
azurerm_service_plan.appservice: Refreshing state...
[id=/subscriptions/subid/resourceGroups/ApressAzureTerraformCH02/providers/Mic
azurerm_linux_web_app.webapp: Refreshing state...
[id=/subscriptions/subid/resourceGroups/ApressAzureTerraformCH02/providers/Mic

Changes to Outputs:
+ web_app_url = "apresstfwebapp.azurewebsites.net"

You can apply this plan to save these new output values to the Terraform state
infrastructure.

Do you want to perform these actions?


Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value: yes

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:
web_app_url = "apresstfwebapp.azurewebsites.net"
The previous example shows one output; however, in more complex deployments, we could output
almost any attribute in the deployment.

Using a Git Ignore File with Terraform


Before we start adding more code and configuration, I’d like to take a moment to discuss the importance of
using a .gitignore file with Terraform, in case you’re planning to use source control systems like GitHub
or Azure Repos to store your code.
Storing state files in the .terraform directory isn’t recommended, as these files should be protected
and encrypted.
To protect your source code, I recommended using a .gitignore file in your repository and exclude a
number of files. With a .gitignore file, we tell Git which files should be ignored and not tracked by Git.
To create a .gitignore file in our repository, we can create one by using the following command. The
command should be executed in the same directory as your repository.

touch .gitignore

To exclude Terraform configuration files, I use the following configuration:

# Ignore Terraform state files


*.tfstate
*.tfstate.*

# Ignore .terraform directory, used to store plugins and state snapshots


.terraform/

# Ignore any local backup files


*~

# Ignore logs
*.log

# Ignore Mac-specific files


.DS_Store

# Ignore Visual Studio Code settings


.vscode/

# Ignore Terraform plan output files


*.tfplan

# Ignore sensitive files with secrets or API keys


secrets.tfvars
*.pem

# Ignore any generated files or directories


/bin/
/out/

If the .gitignore file is working, you’ll see the ignored files marked in white rather than green, as
shown in Figure 2-3, indicating that they are not being tracked.
Adding files to the .gitignore file after they’ve been tracked won’t remove them from the repository;
it will only prevent future changes from being staged.
To stop tracking files that Git already tracks, use the following Git command:

Git rm --cached
Figure 2-3 Terraform file being ignored by Git, as indicated by being marked in white

Using the Global Git Ignore File


We can also make a global .gitignore file that will apply to multiple repositories by taking the following
steps:
1. Create a .gitignore file outside your repository indicating all the files you’d like Git to ignore and not
track.

2. After adding the file, open a terminal window and find the repository with which you’d like to use the
global file, then run the following command:

git config --global core.excludesfile ~/.gitignore_global

Cleaning Up Our Deployment


Before moving onto the next section, let’s delete the Web App for Containers we just deployed using the
following command:

Terraform destroy

Managing Web App for Containers


In this section, we’ll focus on managing Web App for Containers and look into Azure features that can
improve the deployment and management of apps running on Azure Web App for Containers.

Scaling
The first feature I want to touch on is the management of resources a Web App uses in terms of RAM and
CPU. As I mentioned earlier, Terraform has the capability of managing almost any aspect of our deployment
and scaling apps is one of them.
Regarding scaling, Azure Web Apps resources are managed at the app service plan resource we have in
our configuration. The code is as follows:

resource "azurerm_service_plan" "appservice" {


name = "Linux"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Linux"
sku_name = "P1v2"
}
If you look closely at the code, we manage the resources by assigning a Stock Keeping Unit (SKU) using
the sku_name option. Currently, Azure offers ten app service plan options for Linux, as listed in Figure 2-4.

Figure 2-4 App service plan options for Linux

The process of adding more resources to an app service plan is called “scale up,” and the opposite
process is called “scale out.”
To change an app service plan, we just need to change the sku_name value as follows, and then run
Terraform apply.

resource "azurerm_service_plan" "appservice" {


name = "Linux"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Linux"
sku_name = "S2"
}

Backing Up Web Apps


Microsoft Azure backs up all deployed web apps every hour by default. Azure offers two types of backups,
automatic and custom.
Automatic backups are enabled by default at the following pricing tiers:
basic
standard
premium
isolated
With automatic backup, we are limited to 30 GB of backup, and backups run every hour without the
option to run manual backups. Backups are retained for 30 days and cannot be downloaded to a local
machine.
If you require a custom approach to your backups, you can use a custom backup by setting up a storage
account to hold the backups. Once configured, the backup frequency and the retention period can be
configured and changed.
Custom backups can be downloaded to an Azure storage blob.

Customizing Deployment
Before we move on to the next section, I’d like to show you how powerful Terraform is when it comes to
customized deployments. In the following example, we’re going to generate a random web app name for our
application using Terraform.
To make our deployments easier and much more customized, Terraform has created a few providers that
can help us generate random numbers, IDs, passwords, and more.
Going back to our Web App for Containers code, I’m now going to add a new code block that will
generate a random number that I will use to make my web app name.
In the following code block, we’ll use the random provider to generate a random number and use it to
create the name of our web app. The provider details are available at
https://registry.terraform.io/providers/hashicorp/random/latest/docs.

# Generate a random int


resource "random_integer" "random" {
min = 1
max = 20

}
In essence, this code will generate a random number between 1 and 20. I will use that number in the web
app code block to form my web app name and URL.

resource "azurerm_linux_web_app" "webapp" {


name = "ApressTFWebApp${random_integer.random.result}"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.appservice.id

site_config {
always_on = "true"

application_stack {
docker_image_name = "httpd:latest"
docker_registry_url = "https://index.docker.io/"

}
}
app_settings = {
"DOCKER_ENABLE_CI" = "true"
}

When I run the Terraform apply command, Terraform will generate a number and use it to form the
web app URL, the result of which will be:

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

web_app_url = "apresstfwebapp18.azurewebsites.net"

The URL has now been formed and has the number 18 in it.

Variable Interpolation
You probably noticed that in the part of the previous code where we generated the number and formed the
web app URL we used the following code to form the name:

"ApressTFWebApp${random_integer.random.result}"

This example is perfect for taking the opportunity to introduce the concept of variable interpolation.
In Terraform, variable interpolation is the process of using the values of variables within your Terraform
configuration. Interpolation uses the following syntax:
${}
There are two types of variable interpolation:
Variable: Used to reference the value of a variable.
Resource: Used to reference the value of a resource (used in our web app configuration).

Securing Web App for Containers


In the final section of this chapter, we are going to focus on a few security features that are available to us
and can be configured with Terraform, and I will provide examples of how to use them.

HTTPS
Azure Web Apps allows us to secure our applications using the HTTPS protocol, and by default, every
deployment comes with an HTTPS URL enabled. To take this configuration a step further, we can also disable
the use of HTTP using Terraform.
We can add the following line to the web app block if we want to make our web app support HTTPS only:

https_only = "true"

We can also enforce our web application to communicate using only the transport layer security (TLS)
1.2 HTTPS protocol and disable the use of unsecured TLS protocols like TLS 1.0.
The following line of code will set the minimum TLS protocol to 1.2:

minimum_tls_version = "1.2"

Another security feature that we can use is static IP restriction. By default, access to our web service is
available to all IP (Internet protocol) addresses; however, we can limit which IP addresses have access to our
application using IP restrictions.
The following code block adds restrictions to our web app from a static IP block:

ip_restriction {
ip_address = "10.0.0.0/24"
action = "Allow"
# }

In the following code we will add the following security settings:


HTTPS only
Minimum TLS version
IP restrictions

resource "azurerm_linux_web_app" "webapp" {


name = "ApressTFWebApp${random_integer.random.result}"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.appservice.id

https_only = "true"

site_config {
always_on = "true"
minimum_tls_version = "1.2"
application_stack {
docker_image_name = "httpd:latest"
docker_registry_url = "https://index.docker.io/"
}

ip_restriction { # Use only if needed


ip_address = "10.0.0.0/24"
action = "Allow"
}

}
app_settings = {
"DOCKER_ENABLE_CI" = "true"
}

Private Endpoints
Private endpoints for web apps provide the ultimate security feature for securing web apps in Azure. These
endpoints only allow access to web apps from private networks and block access to them by general users
on the Internet.
A private network can be either an Azure Virtual Network (Vnet) or an on-premises network.
Private endpoints allow access to web apps from on-premises networks only or from Azure private
networks.
To configure a private endpoint, we must create a Vnet and place the web app inside the network within
the internal network interface controller (NIC).
In brief, Azure private endpoints use a private network interface that is available on a virtual network.
When a private endpoint is being created, a private IP address is assigned to the web app instead of a public
IP address.
We can also use access restrictions to white list or blacklist specific IP ranges or IP addresses.
To access a private endpoint from a Vnet, Azure uses a private domain name system (DNS) zone to
resolve the private IP address.

Configuring Terraform for a Private Endpoint


The following Terraform configuration will create Web App for Containers using the same web app
configuration we used earlier in this chapter, but here we’ll instead configure the web app to use a private
endpoint.
To do this configuration, we’ll need the following resources:
Azure Virtual Network
Azure Subnet
Virtual network connectivity
A Private DNS zone
a Private Endpoint
The configuration follows:

resource "azurerm_resource_group" "rg" {


name = "ApressAzureTerraformCH02.2"
location = "Australia Southeast"
}

resource "random_integer" "random" {


min = 1
max = 20
}

resource "azurerm_virtual_network" "azvnet" {


name = "Vnet-WebAPP"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
address_space = ["10.0.0.0/16"]
}
resource "azurerm_subnet" "webappssubnet" {
name = "webappssubnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.azvnet.name
address_prefixes = ["10.0.1.0/24"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
}
}
}

resource "azurerm_subnet" "privatesubnet" {


name = "privatesubnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.azvnet.name
address_prefixes = ["10.0.2.0/24"]
private_endpoint_network_policies_enabled = true
}

resource "azurerm_service_plan" "appservice" {


name = "Linux"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Linux"
sku_name = "P1v2"
}

resource "azurerm_linux_web_app" "webapp" {


name = "ApressTFFront${random_integer.random.result}"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.appservice.id

https_only = "true"

site_config {
always_on = "true"
minimum_tls_version = "1.2"
application_stack {
docker_image_name = "nginx:latest"
docker_registry_url = "https://index.docker.io/"
}

}
app_settings = {
"DOCKER_ENABLE_CI" = "true"
vnet_route_all_enabled = "true"

resource "azurerm_app_service_virtual_network_swift_connection"
"vnetintegrationconnection" {
app_service_id = azurerm_linux_web_app.webapp.id
Another random document with
no related content on Scribd:
Mr. Tower is herewith inclosed for your confidential
information. The commercial interests of Great Britain and
Japan will be so clearly served by the desired declaration of
intentions, and the views of the Governments of these
countries as to the desirability of the adoption of measures
insuring the benefits of equality of treatment of all foreign
trade throughout China are so similar to those entertained by
the United States, that their acceptance of the propositions
herein outlined and their coöperation in advocating their
adoption by the other powers can be confidently expected. I
inclose herewith copy of the instruction which I have sent to
Mr. Choate on the subject. In view of the present favorable
conditions, you are instructed to submit the above
considerations to His Imperial German Majesty's minister for
foreign affairs, and to request his early consideration of the
subject. Copy of this instruction is sent to our ambassadors
at London and at St. Petersburg for their information."
Subsequently the same proposal was addressed to the
governments of France, Italy and Japan.

{103}

On the 30th of November, Lord Salisbury addressed to


Ambassador Choate the reply of his government, as follows: "I
have the honor to state that I have carefully considered, in
communication with my colleagues, the proposal contained in
your excellency's note of September 22 that a declaration
should be made by foreign powers claiming 'spheres of
interest' in China as to their intentions in regard to the
treatment of foreign trade and interest therein. I have much
pleasure in informing your excellency that Her Majesty's
Government will be prepared to make a declaration in the sense
desired by your Government in regard to the leased territory
of Wei-hai Wei and all territory in China which may hereafter
be acquired by Great Britain by lease or otherwise, and all
spheres of interest now held or that may hereafter be held by
her in China, provided that a similar declaration is made by
other powers concerned."

Ambassador Porter, at Paris, received a prompt reply, December


16, from the French Minister for Foreign Affairs, M. Delcassé,
in the following note:

"The declarations which I made in the Chamber on the 24th of


November last, and which I have had occasion to recall to you
since then, show clearly the sentiments of the Government of
the Republic. It desires throughout the whole of China and,
with the quite natural reservation that all the powers
interested give an assurance of their willingness to act
likewise, is ready to apply in the territories which are
leased to it, equal treatment to the citizens and subjects of
all nations, especially in the matter of customs duties and
navigation dues, as well as transportation tariffs on rail
ways."

Viscount Aoki, Minister for Foreign Affairs, replied for the


government of Japan, December 26, in the following note to
Minister Buck: "I have the happy duty of assuring your
excellency that the Imperial Government will have no
hesitation to give their assent to so just and fair a proposal
of the United States, provided that all the other powers
concerned shall accept the same."

The reply of the Russian government was addressed to


Ambassador Tower by Count Mouravieff, on the 30th of December,
in the following terms:

"In so far as the territory leased by China to Russia is


concerned, the Imperial Government has already demonstrated
its firm intention to follow the policy of 'the open door' by
creating Dalny (Ta-lien-wan) a free port; and if at some
future time that port, although remaining free itself, should
be separated by a customs limit from other portions of the
territory in question, the customs duties would be levied, in
the zone subject to the tariff, upon all foreign merchandise
without distinction as to nationality. As to the ports now
opened or hereafter to be opened to foreign commerce by the
Chinese Government, and which lie beyond the territory leased
to Russia, the settlement of the question of customs duties
belongs to China herself, and the Imperial Government has no
intention whatever of claiming any privileges for its own
subjects to the exclusion of other foreigners. It is to be
understood, however, that this assurance of the Imperial
Government is given upon condition that a similar declaration
shall be made by other Powers having interests in China. With
the conviction that this reply is such as to satisfy the
inquiry made in the aforementioned note, the Imperial
Government is happy to have complied with the wishes of the
American Government, especially as it attaches the highest
value to anything that may strengthen and consolidate the
traditional relations of friendship existing between the two
countries."

On the 7th of January the reply of the Italian government was


addressed to Minister Draper, at Rome, by the Marquis Visconti
Venosta, as follows: "Supplementary to what you had already
done me the honor of communicating to me in your note of
December 9, 1899, your excellency informed me yesterday of the
telegraphic note received from your Government that all the
powers consulted by the cabinet of Washington concerning the
suitability of adopting a line of policy which would insure to
the trade of the whole world equality of treatment in China
have given a favorable reply. Referring to your communications
and to the statements in my note of December 23 last, I take
pleasure in saying that the Government of the King adheres
willingly to the proposals set forth in said note of December
9."

Finally, on the 19th of February, Count von Bülow wrote to


Ambassador White, at Berlin:
"As recognized by the Government of the United States of
America, according to your excellency's note, … the Imperial
Government has from the beginning not only asserted but also
practically carried out to the fullest extent in its Chinese
possessions absolute equality of treatment of all nations with
regard to trade, navigation, and commerce. The Imperial
Government entertains no thought of departing in the future
from this principle, which at once excludes any prejudicial or
disadvantageous commercial treatment of the citizens of the
United States of America, so long as it is not forced to do
so, on account of considerations of reciprocity, by a
divergence from it by other governments. If, therefore, the
other powers interested in the industrial development of the
Chinese Empire are willing to recognize the same principles,
this can only be desired by the Imperial Government, which in
this case upon being requested will gladly be ready to
participate with the United States of America and the other
powers in an agreement made upon these lines, by which the
same rights are reciprocally secured."

Having, now, the assent of all the Powers which hold leased
territory or claim "spheres of interest" in China, Secretary
Hay sent instructions to the Ambassadors and Ministers
representing the government of the United States at the
capital of each, in the following form:

"The —— Government having accepted the declaration suggested


by the United States concerning foreign trade in China, the
terms of which I transmitted to you in my instruction Number
—— of ——, and like action having been taken by all the various
powers having leased territory or so-called 'spheres of
interest' in the Chinese Empire, as shown by the notes which I
herewith transmit to you, you will please inform the
government to which you are accredited that the condition
originally attached to its acceptance—that all other powers
concerned should likewise accept the proposals of the United
States—having been complied with, this Government will
therefore consider the assent given to it by —— as final and
definitive."

United States, 56th Congress, 1st Session,


House Document Number 547.

{104}

CHINA: A. D. 1900 (January).


Imperial Decree relative to the succession to the Throne.

The following is a translation of an Imperial Decree, "by the


Emperor's own pen," which appeared in the "Peking Gazette,"
January 24, 1900:

"When at a tender age we entered into the succession to the


throne, Her Majesty the Empress-Dowager graciously undertook
the rule of the country as Regent, taught and guided us with
diligence, and managed all things, great and small, with
unremitting care, until we ourself assumed the government.
Thereafter the times again became critical. We bent all our
thoughts and energies to the task of ruling rightly, striving
to requite Her Majesty's loving kindness, that so we might
fulfil the weighty duties intrusted to us by the late Emperor
Mu Tsung Yi (T'ung Chih). But since last year we have suffered
from ill-health, affairs of State have increased in magnitude
and perplexity, and we have lived in constant dread of going
wrong. Reflecting on the supreme importance of the worship of
our ancestors and of the spirits of the land, we therefore
implored the Empress-Dowager to advise us in the government.
This was more than a year ago, but we have never been restored
to health, and we have not the strength to perform in person
the great sacrifices at the altar of Heaven and in the temples
of the spirits of the land. And now the times are full of
difficulties. We see Her Gracious Majesty's anxious toil by
day and by night, never laid aside for rest or leisure, and
with troubled mind we examine ourself, taking no comfort in
sleep or food, but ever dwelling in thought on the labours of
our ancestors in founding the dynasty, and ever fearful lest
our strength be not equal to our task.

"Moreover, we call to mind how, when we first succeeded to the


throne, we reverently received the Empress-Dowager's Decree
that as soon as a Prince should be born to us he should become
the heir by adoption to the late Emperor Mu Tsung Yi (T'ung
Chih). This is known to all the officials and people
throughout the Empire. But we suffer from an incurable
disease, and it is impossible for us to beget a son, so that
the Emperor Mu Tsung Yi has no posterity, and the consequences
to the lines of succession are of the utmost gravity.
Sorrowfully thinking on this, and feeling that there is no
place to hide ourself for shame, how can we look forward to
recovery from all our ailments? We have therefore humbly
implored Her Sacred Majesty carefully to select from among the
near branches of our family a good and worthy member, who
should found a line of posterity for the Emperor Mu Tsung Yi
(T'ung Chih), and to whom the Throne should revert hereafter.
After repeated entreaties, Her Majesty has now deigned to
grant her consent that P'u Chün, son of Tsai Yi, Prince Tuan,
should be adopted as the son of the late Emperor Mu Tsung Yi
(T'ung Chih). We have received Her Majesty's Decree with
unspeakable joy, and in reverent obedience to her gracious
instruction we appoint P'u Chün, son of Tsai Yi, as Prince
Imperial, to carry on the dynastic succession. Let this Decree
be made known to all men."

Great Britain, Parliamentary Publications


(Papers by Command: China, Number 3, 1900, pages 15-16).

CHINA: A. D. 1900 (January-March).


First accounts of the secret society of "the Boxers"
and their bloody work.
The murder of Mr. Brooks, the missionary.
Prolonged effort of foreign Ministers to procure an Imperial
Edict for the suppression of the hostile secret societies.
A naval demonstration recommended.
Testimony of Sir Robert Hart as to the causes and the
patriotic inspiration of the Boxer movement.

The year 1900 opened with news of the murder of Mr. Brooks, of
the Church of England Mission in northern Shantung, who was
wounded and captured December 30 and beheaded the day
following, by a band of marauders belonging to a secret
organization which soon became notorious under the name of the
society of "the Boxers." The British Minister at Peking
reported it to London on the 4th of January, and on the 5th he
gave the following account of the state of affairs in northern
Shantung, where the outrage occurred:

"For several months past the northern part of the Province of


Shantung has been disturbed by bands of rebels connected with
various Secret Societies, who have been defying the
authorities and pillaging the people. An organization known as
the 'Boxers' has attained special notoriety, and their ravages
recently spread over a large portion of Southern Chihli, where
the native Christians appear to have suffered even more than
the rest of the inhabitants from the lawlessness of these
marauders. The danger to which, in both provinces, foreign
missionary establishments have been thus exposed, has been the
subject of repeated representations to the Chinese Government
by others of the foreign Representatives—especially the German
and United States' Ministers—and myself. Early last month the
Governor of Shantung, Yü Hsien, was ordered to vacate his post
and come to Peking for audience, and the General Yüan
Shih-K'ai was appointed Acting Governor in his place. In
Southern Chihli the task of dealing with the disturbances was
entrusted to the Viceroy at Tien-tsin. Her Majesty's Consul at
Tien-tsin has had repeatedly to complain to the latter of the
inadequacy of the protection afforded to British life and
property in the districts affected by the rebellion; and in
consequence of these representations and of my own
communications to the Tsung-li Yamên, guards of soldiers have
been stationed for the special protection of the missionary
premises which were endangered. On the 29th ultimo I took
occasion to warn the Yamên by letter that if the disorder were
not vigorously quelled, international complications were
likely to ensue."

After narrating an interview with the Tsung-li Yamên on the


subject of the murder of Mr. Brooks, and repeating the
assurances he had received of vigorous measures to punish the
murderers, Minister MacDonald concluded his despatch by
saying: "In a note which I addressed to the Yamên this morning
I took occasion to remind the Ministers that there were other
British missionaries living in the district where Mr. Brooks
was killed, and to impress upon their Excellencies the
necessity of securing efficient protection to these. I do not,
however, entertain serious apprehensions as to their safety,
because guards of soldiers have been for some time past
stationed to protect the various missionary residences. The
unfortunate man who was murdered was seized when he was
travelling by wheel-barrow, without escort, through the
country infested by the rebels."

{105}

A few days later, Bishop Scott, of the Church of England


Mission, at Peking, received from Mr. Brown, another
missionary in Shantung province, the following telegram:
"Outlook very black; daily marauding; constant danger; Edict
suppressing published; troops present, but useless; officials
complete inaction: T'ai An Prefect blocks; secret orders from
Throne to encourage." On this Sir Claude again called upon the
Yamên, and "spoke to them," he says, "in terms of the gravest
warning. While I could not believe it possible, I said, that
the rumours of secret orders from the Throne were true, the
mere fact of the currency of such rumours showed the
impression which the conduct of the Prefect conveyed to the
public. So much was I impressed by this, that I had come
to-day especially to protest against the behaviour of the
Shantung officials. The whole of the present difficulty could
be traced to the attitude of the late Governor of Shantung, Yü
Hsien, who secretly encouraged the seditious Society known as
'the Boxers.' I had again and again pointed out to the
Ministers that until China dealt with the high authorities in
such cases these outrages would not cease. I asked the
Ministers to telegraph to the new Governor Yüan that I had
called at the Yamên that day to complain of the conduct of the
Prefect of T'ai An. The Ministers attempted to excuse the
inertia of the local officials on the plea that their
difficulties were very great. The primary cause of the trouble
was the bad feeling existing between the converts and the
ordinary natives. This had developed until bands of marauders
had formed, who harassed Christians and other natives alike.
The local officials had hitherto not had sufficient force to
cope with so widespread a rising, but now that Yüan and his
troops had been sent to the province they hoped for the speedy
restoration of order. I impressed upon the Ministers in the
most emphatic manner my view of the gravity of the situation.
The Imperial Edict expressing sorrow for what had occurred and
enjoining strong measures was satisfactory so far as it went; but
Her Majesty's Government required something more than mere
words, and would now await action on the part of the Chinese
Government in conformity with their promises."

On the day of this interview (January 11), an Imperial Decree


was issued by the Chinese government, opening in ambiguous
terms and decreeing nothing. "Of late," it said, "in all the
provinces brigandage has become daily more prevalent, and
missionary cases have recurred with frequency. Most critics
point to seditious Societies as the cause, and ask for
rigorous suppression and punishment of these. But reflection
shows that Societies are of different kinds. When worthless
vagabonds form themselves into bands and sworn confederacies,
and relying on their numbers create disturbances, the law can
show absolutely no leniency to them on the other hand, when
peaceful and law-abiding people practise their skill in
mechanical arts for the self-preservation of themselves and
their families, or when they combine in village communities
for the mutual protection of the rural population, this is in
accordance with the public-spirited principle (enjoined by
Mencius) of 'keeping mutual watch and giving mutual help.'
Some local authorities, when a case arises, do not regard this
distinction, but, listening to false and idle rumours, regard
all alike as seditious Societies, and involve all in one
indiscriminate slaughter. The result is that no distinction
being made between the good and the evil, men's minds are
thrown into fear and doubt. This is, indeed, 'adding fuel to
stop a fire,' 'driving fish to the deep part of the pool to
catch them.' It means, not that the people are disorderly, but
that the administration is bad."

The foreign ministers at Peking soon learned that this


ambiguous decree had given encouragement to the "Boxers," and
the British, American, German, French and Italian
representatives, by agreement, addressed an "identic note" to
the Yamên, dated January 27, in which, referring to the state
of affairs in north Shantung and in the centre and south of
Chihli, each one said: "This state of affairs, which is a
disgrace to any civilized country, has been brought about by
the riotous and lawless behaviour of certain ruffians who have
banded themselves together into two Societies, termed
respectively the 'Fist of Righteous Harmony' and the 'Big
Sword Society,' and by the apathy, and in some instances
actual connivance and encouragement of these Societies by the
local officials. The members of these Societies go about
pillaging the homes of Christian converts, breaking down their
chapels, robbing and ill-treating inoffensive women and
children, and it is a fact, to which I would draw the special
attention of your Highness and your Excellencies, that on the
banners which are carried by these riotous and lawless people
are inscribed the words, 'Exterminate the Foreigners.'
"On the 11th January an Imperial Decree was issued drawing a
distinction between good and bad Societies. The wording of
this Decree has unfortunately given rise to a widespread
impression that such Associations as the 'Fist of Righteous
Harmony' and the 'Big Sword Society' are regarded with favour
by the Chinese Government, and their members have openly
expressed their gratification and have been encouraged by the
Decree to continue to carry on their outrages against the
Christian converts. I cannot for a moment suppose that such
was the intention of this Decree. These Societies are, as I
have shown, of a most pernicious and rebellious character.

"I earnestly beg to draw the serious attention of the Throne


to the circumstances above described: the disorders have not
reached such a stage that they cannot be stamped out by prompt
and energetic action: but if such action be not immediately
taken, the rioters will be encouraged to think that they have
the support of the Government and proceed to graver crimes,
thereby seriously endangering international relations. As a
preliminary measure, and one to which I attach the greatest
importance, I have to beg that an Imperial Decree be published
and promulgated, ordering by name the complete suppression and
abolition of the 'Fist of Righteous Harmony' and the 'Big
Sword Societies,' and I request that it may be distinctly
stated in the Decree that to belong to either of these
Societies, or to harbour any of its members, is a criminal
offence against the laws of China."

{106}

In communicating the above note to Lord Salisbury, Sir Claude


MacDonald explained: "The name of the Society given in the
note as 'The Fist of Righteous Harmony' is the same as the
'Boxers.' The latter name was given in the first instance,
either by missionaries or newspapers, but does not convey the
meaning of the Chinese words. The idea underlying the name is
that the members of the Society will unite to uphold the cause
of righteousness, if necessary by force."

On the 21st of February no reply to the identic note had been


given, and the five foreign Ministers then wrote again. This
brought an answer so evasive that they asked for an interview
with the Yamên, and it was appointed for March 2d. On the
evening of the 1st they received copies of a proclamation
which the Governor-General of Chihli had been commanded to
issue. The proclamation embodied an Imperial Decree,
transmitted to the Governor-General on the 21st of February,
which said: "Last year the Governor of Shantung telegraphed
that the Society known as 'the Fist of Righteous Harmony' in
many of his districts, under the plea of enmity to foreign
religions, were raising disturbances in all directions, and
had extended their operations into the southern part of
Chihli. We have repeatedly ordered the Governor-General of
Chihli and the Governor of Shantung to send soldiers to keep
the peace. But it is to be feared that if stern measures of
suppression of such proceedings as secretly establishing
societies with names and collecting in numbers to raise
disturbances be not taken, the ignorant populace will be
deluded and excited, and as time goes on things will grow
worse, and when some serious case ensues we shall be compelled
to employ troops to extirpate the evil. The sufferers would be
truly many, and the throne cannot bear to slay without
warning. Let the Governor-General of Chihli and the Governor
of Shantung issue the most stringent Proclamations admonishing
the people and strictly prohibiting (the societies) so that
our people may all know that to secretly establish societies
is contrary to prohibition and a breach of the law."

To this the Governor-General of Chihli added, in his own name:


"I (the Governor-General) find it settled by decided cases
that those people of no occupation, busybodies who style
themselves Professors, and practise boxing, and play with
clubs, and teach people their arts; those also who learn from
these men, and those who march about and parade the villages
and marts flourishing tridents, and playing with sticks,
hood-winking the populace to make a profit for themselves, are
strictly forbidden to carry on such practices. Should any
disobey, on arrest the principals will receive 100 blows with
the heavy bamboo, and be banished to a distance of 1,000
miles. The pupils will receive the same beating, and be
banished to another province for three years, and on
expiration of that period and return to their native place be
subjected to strict surveillance. Should any inn, temple or
house harbour these people without report to the officials, or
should the police and others not search them out and arrest
them, the delinquents will be sentenced to eighty blows with
the heavy bamboo for improper conduct in the higher degree.

"From this it appears that teaching or practising boxing and


club play, and deluding the people for private gain are
fundamentally contrary to law. But of late some of the
ignorant populace have been deluded by ruffians from other
parts of the Empire who talk of charms and incantations and
spiritual incarnations which protect from guns and cannon.
They have dared to secretly establish the Society of the Fist
of Righteous Harmony and have practised drill with fists and
clubs. The movement has spread in all directions, and under
the plea of hatred of foreign religions these people have
harried the country. When soldiers and runners came to make
arrests, turbulent ruffians had the audacity to defy them,
relying on their numbers, thereby exhibiting a still greater
contempt for the law. …

"In addition to instructing all the local officials to adopt


strict measures of prohibition and to punish without fail all
offenders, I hereby issue this most stringent admonition and
notify all people in my jurisdiction, gentry and every class
of the population, that you should clearly understand that the
establishment and formation of secret societies for the
practice of boxing and club exercises are contrary to
prohibition and a breach of the law. The assembly of mobs to
create disturbances and all violent outrages are acts which
the law will still less brook. … The converts and the ordinary
people are all the subjects of the throne, and are regarded by
the Government with impartial benevolence. No distinction is
made between them. Should they have lawsuits they must bow to
the judgments of the officials. The ordinary people must not
give way to rage, and by violent acts create feuds and
trouble. The converts on the other hand must not stir up
strife and oppress the people or incite the missionaries to
screen them and help them to obtain the upper hand."

According to appointment, the interview with the Yamên took


place on the 2d of March: "Mr. Conger, United States'
Minister, Baron von Ketteler, German Minister, Marquis
Salvago, Italian Minister, Baron d'Anthoüard, French Charge d'
Affaires, and myself," writes Sir Claude MacDonald, "were
received at the Yamên by Prince Ch'ing and nearly all the
Ministers. On behalf of myself and my colleagues I
recapitulated the circumstances, as detailed above, which had
led to the demand which we now made. My colleagues all
expressed to the Prince and Ministers their entire concurrence
with the language I used, Mr. Conger reminded the Yamên of the
incredulity with which they had listened to his
representations regarding these disturbances over three months
ago, and the promises they had been making ever since, from
which nothing had resulted. Baron von Ketteler laid special
stress on the fact that in the Decree just communicated no
mention was made of the 'Ta Tao Hui,' or 'Big Knife Society,'
the denunciation of which, equally with that of the
'I-Ho-Ch'uan,' or 'Fist of Righteous Harmony,' had been
demanded. The Prince and Ministers protested emphatically that
the Throne was earnest in its determination to put a stop to
the outrages committed by these Societies. They maintained
that the method adopted for promulgating the Imperial Decree,
that of sending it to the Governors of the provinces
concerned, to be embodied in a Proclamation and acted upon,
was much speedier and more effective than that of publishing a
Decree in the 'Peking Gazette,' as suggested by us. With regard
to the omission of the term 'Ta Tao Hui' from the Decree, they
declared that this Society was now the same as the
'I-Ho-Ch'uan.'"

{107}

At the close of the interview the five Ministers presented


identic notes to the Yamên, in which each said: "I request
that an Imperial Decree may be issued and published in the
'Peking Gazette' ordering by name the complete suppression and
abolition of the 'Fist of Righteous Harmony' and 'Big Sword
Societies,' and I request that it may be distinctly stated in
the Decree that to belong to either of these societies or to
harbour any of its members is a criminal offence against the
law of China. Nothing less than this will, I am convinced, put
an end to the outrages against Christians which have lately
been so prevalent in Chihli and Shantung. Should the Chinese
Government refuse this reasonable request I shall be compelled
to report to my Government their failure to take what may be
called only an ordinary precaution against a most pernicious
and anti-foreign organization. The consequences of further
disorder in the districts concerned cannot fail to be
extremely serious to the Chinese Government."

The reply of the Yamên to this "identic note" was a lengthy


argument to show that publication in the "Peking Gazette" of
the Imperial Edict against "Boxers" would be contrary to "an
established rule of public business in China which it is
impossible to alter"; and that, furthermore, it would be
useless, because the common people of the provinces would not
see it. Not satisfied with this reply, the Ministers, on the
10th of March, addressed another identic note to the Yamên, in
the following words: "Acknowledging receipt of your Highness'
and your Excellencies' note of the 7th March, I regret to say
that it is in no way either an adequate or satisfactory reply
to my notes or my verbal requests concerning the suppression
of the two Societies known as the 'Big Sword' and 'Fist of
Righteous Harmony.' I therefore am obliged to repeat the
requests, and because of the rapid spread of these Societies,
proof of which is accumulating every day, and which the
Imperial Decree of the 11th January greatly encouraged, I
insist that an absolute prohibitive Decree for all China,
mentioning these two Societies by name, be forthwith issued
and published in the 'Peking Gazette,' as was done with the
Decree of the 11th January. Should I not receive a favourable
answer without delay, I shall report the matter to my
Government, and urge strongly the advisability of the adoption
of other measures for the protection of the lives and property
of British subjects in China."

On the same day, each of the Ministers cabled the following


recommendation to his government:

"If the Chinese Government should refuse to publish the Decree


we have required, and should the state of affairs not
materially improve, I would respectfully recommend that a few
ships of war of each nationality concerned should make a naval
demonstration in North Chinese waters. Identic recommendations
are being telegraphed home by my four colleagues
above-mentioned."

On the 16th, Sir Claude wrote: "No reply has yet been received
from the Tsung-li Yamên to the note of the 10th March, and it
was with serious misgivings as to the attitude of the Chinese
Government on this question that I read yesterday the official
announcement of the appointment of Yü Hsien, lately Governor
of Shantung, to the post of Governor of Shansi. The growth and
impunity of the anti-Christian Societies in Shantung has been
universally ascribed to the sympathy and encouragement
accorded to them by this high officer, and his conduct has for
some time past formed the subject of strong representations on
the part of several of the foreign Representatives."
Great Britain, Papers by Command:
China, Number 3, 1900, pages 3-26.

"The foundation of the 'Boxers' can be traced to one man, Yü


Hsien, who, when Prefect of Tsao-chau, in the south-west
corner of Shan-tung, organized a band of men as local militia
or trainbands. For them he revived the ancient appellation of
'I-Ho-Ch'üan,' the Patriotic Harmony Fists. Armed with long
swords, they were known popularly as the Ta-tao-huei, or Big
Knife Society. After the occupation of Kiao-chau Bay the
society grew in force, the professed objects of its members
being to oppose the exactions of native Catholics and to
resist further German aggression. They became anti-Christian
and anti-foreign. They became a religious sect, and underwent
a fantastic kind of spiritual training of weird incantations
and grotesque gymnastics, which they professed to believe
rendered them impervious to the sword and to the bullet of the
white man. Three deities they specially selected as their
own—namely, Kwanti, the God of War and patron deity of the
present dynasty, Kwang Chéng-tze, an incarnation of Laotze,
and the Joyful Buddha of the Falstaffian Belly. They made
Taoist and Buddhist temples their headquarters. Everywhere
they declared that they would drive the foreigner and his
devilish religion from China. To encourage this society its
founder, Yü Hsien, was in March, 1899, appointed by the Throne
Governor of Shan-tung. In four years he had risen from the
comparatively humble post of Prefect to that of the highest
official in the province."

Peking Correspondence London Times,


October 13, 1900.

Sir Robert Hart, an English gentleman who had been in the


service of the Chinese government at Peking for many years,
administering its maritime customs, is the author of an
account of the causes and the character of the Boxer movement,
written since its violent outbreak, from which the following
passages are taken:

"For ages China had discountenanced the military spirit and


was laughed at by us accordingly, and thus, ever since
intercourse under treaties has gone on, we have been lecturing
the Government from our superior standpoint, telling it that
it must grow strong—must create army and navy—must adopt
foreign drill and foreign weapons—must prepare to hold its own
against all comers—must remember 'Codlin' is its friend, not
'Short': our words did not fall on closed ears—effect was
given to selected bits of advice—and various firms did a very
remarkable and very remunerative trade in arms. But while the
Chinese Government made a note of all the advice its generous
friends placed at its disposal, and adopted some suggestions
because they either suited it or it seemed polite and harmless
to do so, it did not forget its own thirty centuries of
historic teaching, and it looked at affairs abroad through its
own eyes and the eyes of its representatives at foreign
Courts, studied their reports and the printed utterances of
books, magazines, and newspapers, and the teaching thus
received began gradually to crystallise in the belief that a
huge standing army on European lines would be wasteful and
dangerous and that a volunteer association—as suggested by the
way all China ranged itself on the Government side in the
Franco-Chinese affair—covering the whole Empire, offering an
outlet for restless spirits and fostering a united and
patriotic feeling, would be more reliable and effective, an
idea which seemed to receive immediate confirmation from
without in the stand a handful of burghers were making in the
Transvaal: hence the Boxer Association, patriotic in origin,
justifiable in its fundamental idea, and in point of fact the
outcome of either foreign advice or the study of foreign
methods.

{108}
"In the meanwhile the seeds of other growths were being sown
in the soil of the Chinese mind, private and official, and
were producing fruit each after its kind: various commercial
stipulations sanctioned by treaties had not taken into full
account Chinese conditions, difficulties, methods, and
requirements, and their enforcement did not make foreign
commerce more agreeable to the eye of either provincial or
metropolitan officials,—missionary propagandism was at work
all over the country, and its fruits, Chinese Christians, did
not win the esteem or goodwill of their fellows, for, first of
all, they offended public feeling by deserting Chinese for
foreign cults, next they irritated their fellow villagers by
refusing, as Christians, to take part in or share the expenses
of village festivals, and lastly, as Christians again, they
shocked the official mind, and popular opinion also, by
getting their religious teachers, more especially the Roman
Catholics, to interfere on their behalf in litigation, &c., a
state of affairs which became specially talked about in
Shantung, the native province of the Confucius of over 2,000
years ago and now the sphere of influence of one of the
Church's most energetic bishops,—the arrangement by which
missionaries were to ride in green chairs and be recognised as
the equals of Governors and Viceroys had its special
signification and underlined missionary aspiration telling
people and officials in every province what they had to expect
from it: on the top of this came the Kiao Chow affair and the
degradation and cashiering of a really able, popular, and
clean-handed official, the Governor Li Ping Hêng, succeeded by
the cessions of territory at Port Arthur, Wei-Hai-Wei, Kwang
Chow Wan, &c., &c., &c., and these doings, followed by the
successful stand made against the Italian demand for a port on
the Coast of Chekiang, helped to force the Chinese Government
to see that concession had gone far enough and that opposition
to foreign encroachment might now and henceforth be the key-note
of its policy.

"Li Ping Hêng had taken up his private residence in the


southeastern corner of Pecheli, close to the Shantung
frontier, and the Boxer movement, already started in a
tentative way in the latter province, now received an immense
impetus from the occurrences alluded to and was carefully
nurtured and fostered by that cashiered official—more
respected than ever by his countrymen. Other high officials
were known to be in sympathy with the new departure and to
give it their strongest approval and support, such as Hsü
Tung, Kang I, and men of the same stamp and standing, and
their advice to the throne was to try conclusions with
foreigners and yield no more to their demands. However
mistaken may have been their reading of foreigners, and
however wrong their manner of action, these men—eminent in
their own country for their learning and services—were
animated by patriotism, were enraged at foreign dictation, and
had the courage of their convictions: we must do them the
justice of allowing they were actuated by high motives and
love of country—but that does not always or necessarily mean
political ability or highest wisdom. …

"The Chinese, an intelligent, cultivated race, sober,


industrious, and on their own lines civilised, homogeneous in
language, thought, and feeling, which numbers some four
hundred millions, lives in its own ring fence, and covers a
country which—made up of fertile land and teeming waters, with
infinite variety of mountain and plain, hill and dale, and
every kind of climate and condition—on its surface produces
all that a people requires and in its bosom hides untold
virgin wealth that has never yet been disturbed—this race,
after thousands of years of haughty seclusion and
exclusiveness, has been pushed by the force of circumstances
and by the superior strength of assailants into treaty
relations with the rest of the world, but regards that as a
humiliation, sees no benefit accruing from it, and is looking
forward to the day when it in turn will be strong enough to
revert to its old life again and do away with foreign
intercourse, interference, and intrusion: it has slept long,

You might also like