100% found this document useful (1 vote)
16 views

Getting Started with Containers in Azure: Deploy Secure Cloud Applications Using Terraform 2nd Edition Shimon Ifrah download

The document promotes various ebooks available for download on ebookmass.com, including titles focused on Azure, Terraform, Angular, and Linux administration. It highlights the second edition of 'Getting Started with Containers in Azure' by Shimon Ifrah, which provides guidance on deploying secure cloud applications using Terraform. Additionally, it outlines the author's expertise and the structure of the book, which aims to simplify cloud infrastructure deployments using Terraform.

Uploaded by

gulyayesmar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
16 views

Getting Started with Containers in Azure: Deploy Secure Cloud Applications Using Terraform 2nd Edition Shimon Ifrah download

The document promotes various ebooks available for download on ebookmass.com, including titles focused on Azure, Terraform, Angular, and Linux administration. It highlights the second edition of 'Getting Started with Containers in Azure' by Shimon Ifrah, which provides guidance on deploying secure cloud applications using Terraform. Additionally, it outlines the author's expertise and the structure of the book, which aims to simplify cloud infrastructure deployments using Terraform.

Uploaded by

gulyayesmar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 80

Visit https://ebookmass.

com to download the full version and


browse more ebooks or textbooks

Getting Started with Containers in Azure: Deploy


Secure Cloud Applications Using Terraform 2nd
Edition Shimon Ifrah

_____ Press the link below to begin your download _____

https://ebookmass.com/product/getting-started-with-
containers-in-azure-deploy-secure-cloud-applications-using-
terraform-2nd-edition-shimon-ifrah-2/

Access ebookmass.com now to download high-quality


ebooks or textbooks
We believe these products will be a great fit for you. Click
the link to download now, or visit ebookmass.com
to discover even more!

Getting Started with Containers in Azure: Deploy Secure


Cloud Applications Using Terraform 2nd Edition Shimon
Ifrah
https://ebookmass.com/product/getting-started-with-containers-in-
azure-deploy-secure-cloud-applications-using-terraform-2nd-edition-
shimon-ifrah-2/

Getting Started with Angular: Create and Deploy Angular


Applications 1st Edition Victor Hugo Garcia

https://ebookmass.com/product/getting-started-with-angular-create-and-
deploy-angular-applications-1st-edition-victor-hugo-garcia/

Designing Applications for Google Cloud Platform: Create


and Deploy Applications Using Java Ashutosh Shashi

https://ebookmass.com/product/designing-applications-for-google-cloud-
platform-create-and-deploy-applications-using-java-ashutosh-shashi/

Design and Deploy a Secure Azure Environment: Mapping the


NIST Cybersecurity Framework to Azure Services 1st Edition
Puthiyavan Udayakumar
https://ebookmass.com/product/design-and-deploy-a-secure-azure-
environment-mapping-the-nist-cybersecurity-framework-to-azure-
services-1st-edition-puthiyavan-udayakumar/
Using And Administering Linux: Volume 1 Zero To SysAdmin:
Getting Started 2nd Edition David Both

https://ebookmass.com/product/using-and-administering-linux-
volume-1-zero-to-sysadmin-getting-started-2nd-edition-david-both/

Using and Administering Linux: Volume 1: Zero to SysAdmin:


Getting Started, 2nd Edition David Both

https://ebookmass.com/product/using-and-administering-linux-
volume-1-zero-to-sysadmin-getting-started-2nd-edition-david-both-2/

Programming Arduino: Getting Started with Sketches (Tab)


Monk

https://ebookmass.com/product/programming-arduino-getting-started-
with-sketches-tab-monk/

Deploy Container Applications Using Kubernetes:


Implementations with microk8s and AWS EKS Shiva
Subramanian
https://ebookmass.com/product/deploy-container-applications-using-
kubernetes-implementations-with-microk8s-and-aws-eks-shiva-
subramanian/

Programming Arduino: Getting Started with Sketches, Third


Edition Simon Monk

https://ebookmass.com/product/programming-arduino-getting-started-
with-sketches-third-edition-simon-monk/
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
Other documents randomly have
different content
The Project Gutenberg eBook of Juvenile
Sports; or, Youth's Pastimes
This ebook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and with
almost no restrictions whatsoever. You may copy it, give it away
or re-use it under the terms of the Project Gutenberg License
included with this ebook or online at www.gutenberg.org. If you
are not located in the United States, you will have to check the
laws of the country where you are located before using this
eBook.

Title: Juvenile Sports; or, Youth's Pastimes

Author: Anonymous

Release date: January 1, 2016 [eBook #50817]


Most recently updated: October 22, 2024

Language: English

Credits: Produced by Chris Curnow, ellinora and the Online


Distributed Proofreading Team at http://www.pgdp.net
(This
file was produced from images generously made
available
by The Internet Archive)

*** START OF THE PROJECT GUTENBERG EBOOK JUVENILE


SPORTS; OR, YOUTH'S PASTIMES ***
Transcriber's Note:

Missing periods added at the end of stanzas, otherwise punctuation


and spelling left as in the original.
JUVENILE SPORTS

OR

YOUTH'S PASTIMES

Embellished with Cold. Engras.


Price Sixpence.

London
Pub. by R. Miller, 24 Old Fish S. Doctors Coms.
Would you either skate, or slide,
Ever Oh! of falls beware,
Pain often, stands by pleasures side
Broken heads, are skaiters fare.
The Bear is in a surly mood,
I, should not like him in a wood,
Then buffet him, if you advance,
But mind, this knot, shall make you
dance.
Come, trundle now your Hoops, my
boys,
And drive them quick along,
While each his favorite sport enjoys,
Amidst the jovial throng.
The little Vessel spreads all sail,
Swift wafted by the gentle gale,
And as she glides along the stream,
Their eager eyes, with pleasure beam.
High bounding like the nimble deer
At Leapfrog, blithesome boys appear
While health gives vigour to the frame
And fits them for the active game.
With bat and trap, the Youth's agre'd
To send the ball abroad with speed,
While eager with his open hands,
To catch him out, his playmate stands.
This Boy with spirit, whips his top,
And makes it circling, spin and hop,
Then out of breath, he sits awhile,
To rest him from the pleasing toil.
The Kite majestic soars on high,
In various gambols, thro' the sky,
Deck'd out with stars and colors gay,
Upon the schoolboys holiday.
The time for playing Top is in,
By Proclamation, let them spin,
To drive the counter, to its bound,
Upon the smooth enamell'd ground.
The Pins in even order stand,
Like ranks of soldiers, in a band,
And many a Youth before his prime,
Is fell'd, by that arch bowler—Time.
Now each regardless of a fall,
With crooked stick, oft strikes the ball,
Which o'er the icy surface flies,
The adventr'us game, with ardour plies.
*** END OF THE PROJECT GUTENBERG EBOOK JUVENILE SPORTS;
OR, YOUTH'S PASTIMES ***

Updated editions will replace the previous one—the old editions


will be renamed.

Creating the works from print editions not protected by U.S.


copyright law means that no one owns a United States
copyright in these works, so the Foundation (and you!) can copy
and distribute it in the United States without permission and
without paying copyright royalties. Special rules, set forth in the
General Terms of Use part of this license, apply to copying and
distributing Project Gutenberg™ electronic works to protect the
PROJECT GUTENBERG™ concept and trademark. Project
Gutenberg is a registered trademark, and may not be used if
you charge for an eBook, except by following the terms of the
trademark license, including paying royalties for use of the
Project Gutenberg trademark. If you do not charge anything for
copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such
as creation of derivative works, reports, performances and
research. Project Gutenberg eBooks may be modified and
printed and given away—you may do practically ANYTHING in
the United States with eBooks not protected by U.S. copyright
law. Redistribution is subject to the trademark license, especially
commercial redistribution.

START: FULL LICENSE


THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the


free distribution of electronic works, by using or distributing this
work (or any other work associated in any way with the phrase
“Project Gutenberg”), you agree to comply with all the terms of
the Full Project Gutenberg™ License available with this file or
online at www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand,
agree to and accept all the terms of this license and intellectual
property (trademark/copyright) agreement. If you do not agree
to abide by all the terms of this agreement, you must cease
using and return or destroy all copies of Project Gutenberg™
electronic works in your possession. If you paid a fee for
obtaining a copy of or access to a Project Gutenberg™
electronic work and you do not agree to be bound by the terms
of this agreement, you may obtain a refund from the person or
entity to whom you paid the fee as set forth in paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only


be used on or associated in any way with an electronic work by
people who agree to be bound by the terms of this agreement.
There are a few things that you can do with most Project
Gutenberg™ electronic works even without complying with the
full terms of this agreement. See paragraph 1.C below. There
are a lot of things you can do with Project Gutenberg™
electronic works if you follow the terms of this agreement and
help preserve free future access to Project Gutenberg™
electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright
law in the United States and you are located in the United
States, we do not claim a right to prevent you from copying,
distributing, performing, displaying or creating derivative works
based on the work as long as all references to Project
Gutenberg are removed. Of course, we hope that you will
support the Project Gutenberg™ mission of promoting free
access to electronic works by freely sharing Project Gutenberg™
works in compliance with the terms of this agreement for
keeping the Project Gutenberg™ name associated with the
work. You can easily comply with the terms of this agreement
by keeping this work in the same format with its attached full
Project Gutenberg™ License when you share it without charge
with others.

1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside
the United States, check the laws of your country in addition to
the terms of this agreement before downloading, copying,
displaying, performing, distributing or creating derivative works
based on this work or any other Project Gutenberg™ work. The
Foundation makes no representations concerning the copyright
status of any work in any country other than the United States.

1.E. Unless you have removed all references to Project


Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project
Gutenberg™ work (any work on which the phrase “Project
Gutenberg” appears, or with which the phrase “Project
Gutenberg” is associated) is accessed, displayed, performed,
viewed, copied or distributed:

This eBook is for the use of anyone anywhere in the United


States and most other parts of the world at no cost and
with almost no restrictions whatsoever. You may copy it,
give it away or re-use it under the terms of the Project
Gutenberg License included with this eBook or online at
www.gutenberg.org. If you are not located in the United
States, you will have to check the laws of the country
where you are located before using this eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is


derived from texts not protected by U.S. copyright law (does not
contain a notice indicating that it is posted with permission of
the copyright holder), the work can be copied and distributed to
anyone in the United States without paying any fees or charges.
If you are redistributing or providing access to a work with the
phrase “Project Gutenberg” associated with or appearing on the
work, you must comply either with the requirements of
paragraphs 1.E.1 through 1.E.7 or obtain permission for the use
of the work and the Project Gutenberg™ trademark as set forth
in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is


posted with the permission of the copyright holder, your use and
distribution must comply with both paragraphs 1.E.1 through
1.E.7 and any additional terms imposed by the copyright holder.
Additional terms will be linked to the Project Gutenberg™
License for all works posted with the permission of the copyright
holder found at the beginning of this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files
containing a part of this work or any other work associated with
Project Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute


this electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the
Project Gutenberg™ License.

1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if
you provide access to or distribute copies of a Project
Gutenberg™ work in a format other than “Plain Vanilla ASCII” or
other format used in the official version posted on the official
Project Gutenberg™ website (www.gutenberg.org), you must,
at no additional cost, fee or expense to the user, provide a copy,
a means of exporting a copy, or a means of obtaining a copy
upon request, of the work in its original “Plain Vanilla ASCII” or
other form. Any alternate format must include the full Project
Gutenberg™ License as specified in paragraph 1.E.1.

1.E.7. Do not charge a fee for access to, viewing, displaying,


performing, copying or distributing any Project Gutenberg™
works unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or


providing access to or distributing Project Gutenberg™
electronic works provided that:

• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”

• You provide a full refund of any money paid by a user who


notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.

• You provide, in accordance with paragraph 1.F.3, a full refund of


any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.

• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project


Gutenberg™ electronic work or group of works on different
terms than are set forth in this agreement, you must obtain
permission in writing from the Project Gutenberg Literary
Archive Foundation, the manager of the Project Gutenberg™
trademark. Contact the Foundation as set forth in Section 3
below.

1.F.

1.F.1. Project Gutenberg volunteers and employees expend


considerable effort to identify, do copyright research on,
transcribe and proofread works not protected by U.S. copyright
law in creating the Project Gutenberg™ collection. Despite these
efforts, Project Gutenberg™ electronic works, and the medium
on which they may be stored, may contain “Defects,” such as,
but not limited to, incomplete, inaccurate or corrupt data,
transcription errors, a copyright or other intellectual property
infringement, a defective or damaged disk or other medium, a
computer virus, or computer codes that damage or cannot be
read by your equipment.

1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except


for the “Right of Replacement or Refund” described in
paragraph 1.F.3, the Project Gutenberg Literary Archive
Foundation, the owner of the Project Gutenberg™ trademark,
and any other party distributing a Project Gutenberg™ electronic
work under this agreement, disclaim all liability to you for
damages, costs and expenses, including legal fees. YOU AGREE
THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT
EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE
THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY
DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE
TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL,
PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE
NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.

1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you


discover a defect in this electronic work within 90 days of
receiving it, you can receive a refund of the money (if any) you
paid for it by sending a written explanation to the person you
received the work from. If you received the work on a physical
medium, you must return the medium with your written
explanation. The person or entity that provided you with the
defective work may elect to provide a replacement copy in lieu
of a refund. If you received the work electronically, the person
or entity providing it to you may choose to give you a second
opportunity to receive the work electronically in lieu of a refund.
If the second copy is also defective, you may demand a refund
in writing without further opportunities to fix the problem.

1.F.4. Except for the limited right of replacement or refund set


forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’,
WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.

1.F.5. Some states do not allow disclaimers of certain implied


warranties or the exclusion or limitation of certain types of
damages. If any disclaimer or limitation set forth in this
agreement violates the law of the state applicable to this
agreement, the agreement shall be interpreted to make the
maximum disclaimer or limitation permitted by the applicable
state law. The invalidity or unenforceability of any provision of
this agreement shall not void the remaining provisions.

1.F.6. INDEMNITY - You agree to indemnify and hold the


Foundation, the trademark owner, any agent or employee of the
Foundation, anyone providing copies of Project Gutenberg™
electronic works in accordance with this agreement, and any
volunteers associated with the production, promotion and
distribution of Project Gutenberg™ electronic works, harmless
from all liability, costs and expenses, including legal fees, that
arise directly or indirectly from any of the following which you
do or cause to occur: (a) distribution of this or any Project
Gutenberg™ work, (b) alteration, modification, or additions or
deletions to any Project Gutenberg™ work, and (c) any Defect
you cause.

Section 2. Information about the Mission


of Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new
computers. It exists because of the efforts of hundreds of
volunteers and donations from people in all walks of life.

Volunteers and financial support to provide volunteers with the


assistance they need are critical to reaching Project
Gutenberg™’s goals and ensuring that the Project Gutenberg™
collection will remain freely available for generations to come. In
2001, the Project Gutenberg Literary Archive Foundation was
created to provide a secure and permanent future for Project
Gutenberg™ and future generations. To learn more about the
Project Gutenberg Literary Archive Foundation and how your
efforts and donations can help, see Sections 3 and 4 and the
Foundation information page at www.gutenberg.org.

Section 3. Information about the Project


Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-
profit 501(c)(3) educational corporation organized under the
laws of the state of Mississippi and granted tax exempt status
by the Internal Revenue Service. The Foundation’s EIN or
federal tax identification number is 64-6221541. Contributions
to the Project Gutenberg Literary Archive Foundation are tax
deductible to the full extent permitted by U.S. federal laws and
your state’s laws.

The Foundation’s business office is located at 809 North 1500


West, Salt Lake City, UT 84116, (801) 596-1887. Email contact
links and up to date contact information can be found at the
Foundation’s website and official page at
www.gutenberg.org/contact
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookmasss.com

You might also like