AWS Elastic Beanstalk recently announced support for customizing Windows environments with configuration files. Before this, the only way to customize a .NET container was to create a custom AMI in each region you wanted to run your application in.
Adding a configuration file to your application allows you to
- install packages
- write files in locations other than the application folder
- execute commands, and run scripts
- start services
set configuration options
- for your application
- for the Elastic Beanstalk environment.
Let's walk through a simple example to show how it's done.
Installing packages and starting custom services
Our hypothetical application MyApp relies on a third-party package called WebMagicThingy, which is packaged as an MSI. In addition, we have written a Windows service that periodically performs maintenance and cleanup operations on the host for our application. We want to install and start that service on each instance in our Elastic Beanstalk environment.
The initial step is to make our service code and the third-party package available on the web. We'll put them in an S3 bucket called my-app-support.
Next, we'll create a folder in our application called .ebextensions, and in that folder create a file called MyAppSupport.config. The .ebextensions folder can contain more than one file with a .config extension. You can either include these files in your project, or alternatively you can select All Files in the Project Folder for the Items to deploy option on the Package/Publish Web tab of the project properties pane to ensure that they get included in the deployment bundle.
The format of the configuration files is YAML. Visual Studio expects files with a .config extension to be XML files that conform to a specific schema, so it may be easier to create these files in an external editor, then include them in the project. Ours will look like this:
packages: msi: WebMagicThingy: http://s3.amazonaws.com/my-app-support/WebMagicThingy.msi sources: c:/AppSupport/MyAppJanitor: http://s3.amazonaws.com/my-app-support/MyAppJanitor.zip commands: install-janitor: command: C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\installutil MyAppJanitor.exe cwd: c:/AppSupport/MyAppJanitor waitForCompletion:0 services: windows: MyAppJanitor: enabled: true ensureRunning: true commands: install-janitor
Each level of indentation is two spaces. Take care that your editor doesn't replace consecutive spaces with tabs, or the file will not be interpreted correctly, and Elastic Beanstalk will stop the deployment with an error.
This configuration does four things on each instance in the Elastic Beanstalk environment:
- Installs the MSI that we put in our S3 bucket earlier
- Expands the MyAppJanitor.zip from the S3 bucket to the location C:\AppSupport\MyAppJanitor
Runs installutil.exe to install the MyAppJanitor service
- The cwd: directory allows you to specify what folder the command is run in
- If waitForCompletion is not specified for a command, the container will wait for 60 seconds by default.
- Makes sure that the service is started
You may notice inconsistent use of path separators and escaping in various places in the file. Most directives can use forward-slash as the path separator, but invoking commands that are not in the PATH requires escaped backward-slash path separators.
In upcoming posts, we'll explore other ways to customize Windows Elastic Beanstalk environments with the .ebextensions mechanism. In the meantime, you can explore the Elastic Beanstalk documentation on the topic and see what things you come up with.