Create Docker image with Packer, PowerShell, PowerCLI and Azure DevOps self-hosted agent
Today we will create a Docker image that will contain Packer, Windows Update Provisioner for Packer, PowerShell, PowerCLI and Azure DevOps self-hosted agent.
To automate Packer image creation process we will utilize Azure DevOps, which is a service hosted in public cloud. What we want to do is to create Packer image on-premise in our datacenter, so there is a problem with communication between vCenter server and Azure DevOps.
Azure DevOps agent
Why Azure DevOps agent is needed?
Normally Azure DevOps does not have any connection with our datacenter. To establish connection between on-premise vCenter server and Azure DevOps, a dedicated agent placed inside our datacenter is needed. That agent needs to have network connection with our vCenter server and ESXi hosts. It can be placed in different VLAN, but that VLAN needs to be routable with vCenter and ESXi VLAN.
What Azure Devops agent does?
It actually triggers a tasks initiated from Azure DevOps portal locally in our infrastructure. All files reuired to create our builds needs to be first copied on Azure Devops agent and agent triggers the build job. The files copied on agent from Azure DevOps server are called artifacts. Because agent triggers a build jobs, it needs to be equipped with all necessary tools that are required to create Packer template. Those are:
- Packer
- Packer Windows Update provisioner
- PowerShell
- PowerCLI
Self-hosted Azure DevOps agent
Azure DevOps agent can be hosted in Azure or it can be hosted locally in our DC. Obviously we will need self-hosted agent.
First of all it allows direct communication with our datacenter. Second thing - it’s free. For Azure DevOps agent hosted in Azure you normally needs to pay some money.
Of course everything depends on subscription level you own, but my assumption is that you don’t have any available subscription and want to minimize operational costs.
Remember, or goal is to build secure templates and minimize operational costs!
To establish communication between DevOps server and on-premise vCenter server a dedicated token will be used. This token will have to be generated on Azure Devops portal.
Support platforms for DevOps agents
Azure DevOps agent can be installed on Windows or on Linux. We will choose Linux as our destination platform and there is few reasons for that:
- When utilizing Linux you don’t need to pay for Windows license. Since Azure DevOps agent will just trigger our build tasks, there is no need to pay Windows license for such service.
- When using Linux as agent platform we can utlize Docker and automate process of creating a docker image will all necessary tools.
You could probably use some bash script to automate process of installing and configuring all necessary tools on Linux, but using Docker will be much faster and efficient way to achieve expected result.
- Since DevOps agent keeps all artifacts locally in clear text (including passwords), security is a major concern here. It’s very easy to erase Windows password using some small 3rd party tool and get access to all artifacts and all passwords on that agent. Using Linux and Docker container make a things much harder for potential attacker. We will use other methods to secure data on agent machine but Linux is much better option in terms of security.
Build Ubuntu VM
Create Ubuntu 21.04 Packer image
We could use Windows Subsystem for Linux (WSL) to speedup Docker image creation process but we want to build our final solution which will utilize Ubuntu VM. For this reason we will use Ubuntu 21.04. To create Ubuntu VM Template using Packer use this link.
Customize Ubuntu VM
To make life easier first enable root account and setup new root account password.
|
|
Once done switch to root account typing command:
|
|
Username will change from your existing user to root. This means we have elevated privileges on the system.
Set static IP
|
|
Once done a configuration file will be displayed
Edit the file using nano editor:
|
|
Edit IP, gateway and DNS settings to match your network configuration:
|
|
Type Ctrl+x and confirm saving changes typing y.
|
|
This will apply network settings that has been modified. From now putty can be used to interact with VM through SSH console
Change hostname
Perform fallowing command to change hostname to ld9-vcsabackups01
|
|
Provide server description using fallowing command:
|
|
Once applied verify that changes have been applied
|
|
Upgrade system
Perform server upgrade
|
|
Install Docker Engine and Docker Compose
Install Docker Engine
Docker Engine allow us to run standalone containers.
First remove existing Docker Engine if exists:
|
|
Update the apt package index and install packages to allow apt to use a repository over HTTPS:
|
|
Add Docker’s official GPG key:
|
|
Use the following command to set up the stable repository.
|
|
Install Docker Engine
|
|
Check Docker version:
|
|
Install Docker Compose
Compose is a file format for describing distributed Docker apps, and it’s a tool for managing them. Docker Compose relies on Docker Engine for any meaningful work, so make sure you have Docker Engine installed either locally or remote.
On Linux, you can download the Docker Compose binary from the Compose repository release page on GitHub.
Run this command to download the current stable release of Docker Compose:
|
|
Apply executable permissions to the binary:
|
|
Note: If the command docker-compose fails after installation, check your path. You can also create a symbolic link to /usr/bin or any other directory in your path.
|
|
Test the installation:
|
|
Once Docker Engine and Docker Compose will be installed we need to add existing, non-root user to docker group to perform docker tasks without privileged mode:
|
|
Once added, restart your SSH session to apply changes.
Preparing for Docker container image creation
Inside your home directory create new folder named “Azure-DevOps-Agent”:
|
|
Once we are inside devopsagent folder create new file named Dockerfile
:
|
|
To build container image we need a file named Dockerfile
which will include fallowing content:
|
|
In same directory as Dockerfile
create new file named start.sh
|
|
and paste there fallowing content:
|
|
Alternatively once you are under your home directory run fallowing command:
|
|
Once done you should see Azure-DevOps-Agent folder which will contain three files:
|
|
You can find both files on my GitHub account
Changing product versions
Within Dockerfile I’ve hardcoded particular product versions:
- Packer version 1.7.8
- Windows Update Provisioner version 0.14.0
- PowerShell version 7.1.3
- Azure DevOps agent version 2.195.2
Obviously you may change product versions according your needs. This can be done modifying ARG values directly in the Dockerfile or provide alternative values during building process which will be passed to Dockerfile.
Build Docker image
Finally we are at stage where building process can be initiated.
If product versions has been manually changed directly inside Dockerfile then you can simply run fallowing command:
|
|
This will initiate building process that may take up to 15 minutes.
Alternatively you can pass particular product versions into docker build command:
|
|
With those arguments we are telling Docker to include PowerShell version 7.1.4 instead 7.1.3 and Packer version 1.7.7 instead 1.7.8.
Don’t forget to include .
at the end of build command. This tells where Docker should look for Dockerfile.
Now sit down and relax.
If everything will go well you should see fallowing console output:
|
|
This would mean that our docker image has been created successfully. You can check if container image is visible running fallowing command:
|
|
The output should look like this:
|
|
To run the container we would have to pass few specific values from our Azure DevOps account, but that will be topic for some other blog entry.
Thanks for reading.