<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Donna Malayeri</title><link>https://www.pulumi.com/blog/author/donna-malayeri/</link><description>Pulumi blog posts: Donna Malayeri.</description><language>en-us</language><pubDate>Fri, 20 Jul 2018 00:00:00 +0000</pubDate><item><title>Provisioning and Managing Cloud Infrastructure with Pulumi</title><link>https://www.pulumi.com/blog/provisioning-and-managing-cloud-infrastructure-with-pulumi/</link><pubDate>Fri, 20 Jul 2018 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/provisioning-and-managing-cloud-infrastructure-with-pulumi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/provisioning-and-managing-cloud-infrastructure-with-pulumi/index.png" /&gt;
&lt;p&gt;If you&amp;rsquo;ve been following the blog, you know that Pulumi is great for
building &lt;a href="https://www.pulumi.com/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/"&gt;serverless applications&lt;/a&gt;,
&lt;a href="https://www.pulumi.com/blog/deploying-production-ready-containers-with-pulumi/"&gt;container-based applications&lt;/a&gt;,
and a &lt;a href="https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/"&gt;combination of the two&lt;/a&gt;.
But, did you know that you can manage any cloud resource in AWS, Azure, or Google Cloud Platform?&lt;/p&gt;
&lt;p&gt;You can use the
&lt;a href="https://www.pulumi.com/registry/packages/aws/api-docs/"&gt;AWS&lt;/a&gt;,
&lt;a href="https://www.pulumi.com/registry/packages/azure/api-docs/"&gt;Azure&lt;/a&gt;,
or &lt;a href="https://www.pulumi.com/registry/packages/gcp/api-docs/"&gt;Google Cloud&lt;/a&gt;
libraries to manage cloud resources. Using these libraries, you can
directly manage the properties of any cloud resource.&lt;/p&gt;
&lt;p&gt;For example, in just a few lines of code, you can provision a security
group and an EC2 instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let group = new aws.ec2.SecurityGroup(&amp;quot;web-secgrp&amp;quot;, {
ingress: [
{ protocol: &amp;quot;tcp&amp;quot;, fromPort: 22, toPort: 22, cidrBlocks: [&amp;quot;0.0.0.0/0&amp;quot;] },
],
});
let server = new aws.ec2.Instance(&amp;quot;web-server-www&amp;quot;, {
instanceType: &amp;quot;t2.micro&amp;quot;,
securityGroups: [ group.name ], // reference the group object above
ami: &amp;quot;ami-7172b611&amp;quot;,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, let&amp;rsquo;s add a a CloudWatch metric alarm that is triggered when when
the CPU utilization is over 80%:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const metricAlarm = new aws.cloudwatch.MetricAlarm(&amp;quot;mymetricalarm&amp;quot;, {
comparisonOperator: &amp;quot;GreaterThanOrEqualToThreshold&amp;quot;,
evaluationPeriods: 2,
metricName: &amp;quot;CPUUtilization&amp;quot;,
namespace: &amp;quot;AWS/EC2&amp;quot;,
period: 120,
statistic: &amp;quot;Average&amp;quot;,
threshold: 80,
alarmDescription: &amp;quot;This metric monitors ec2 cpu utilization&amp;quot;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition to alerting, you may want to provision a &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html"&gt;CloudWatch dashboard&lt;/a&gt;
to have a single monitoring view for all your application resources. You
can define this dashboard directly in code using Pulumi. The following
code defines a dashboard and specifies the widgets to include:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const dashboard = new aws.cloudwatch.Dashboard(&amp;quot;mydashboard&amp;quot;, {
dashboardName: &amp;quot;my-dashboard&amp;quot;,
dashboardBody: JSON.stringify({
widgets: [
{
type: &amp;quot;metric&amp;quot;,
x: 0,
y: 0,
width: 12,
height: 6,
properties: {
metrics: [
[
&amp;quot;AWS/EC2&amp;quot;,
&amp;quot;CPUUtilization&amp;quot;,
&amp;quot;InstanceId&amp;quot;,
&amp;quot;i-012345&amp;quot;
]
],
period: 300,
stat: &amp;quot;Average&amp;quot;,
region: &amp;quot;us-east-1&amp;quot;,
title: &amp;quot;EC2 Instance CPU&amp;quot;
}
}
]
})
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perhaps you want to post to an SNS topic whenever a user signs in to the
AWS console for your production account. This requires provisioning
three resources: the SNS topic, a CloudWatch event rule, and a
CloudWatch event target. With Pulumi, this can all be specified with
just a few lines of JavaScript:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const loginsTopic = new aws.sns.Topic(&amp;quot;myloginstopic&amp;quot;);
const eventRule = new aws.cloudwatch.EventRule(&amp;quot;myeventrule&amp;quot;, {
eventPattern: JSON.stringify({
&amp;quot;detail-type&amp;quot;: [
&amp;quot;AWS Console Sign In via CloudTrail&amp;quot;
]
})
});
const eventTarget = new aws.cloudwatch.EventTarget(&amp;quot;myeventtarget&amp;quot;, {
rule: eventRule.name,
targetId: &amp;quot;SendToSNS&amp;quot;,
arn: loginsTopic.arn
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are just a few examples of the AWS resources you can manage in
Pulumi. You can provision
&lt;a href="https://www.pulumi.com/registry/packages/aws/api-docs/athena/"&gt;Athena databases&lt;/a&gt;,
&lt;a href="https://www.pulumi.com/registry/packages/aws/api-docs/dynamodb/"&gt;DynamoDB tables&lt;/a&gt;,
&lt;a href="https://www.pulumi.com/registry/packages/aws/api-docs/iam/"&gt;IAM users, roles, groups, and role policies&lt;/a&gt;,
&lt;a href="https://www.pulumi.com/registry/packages/aws/api-docs/kinesis/"&gt;Kinesis streams&lt;/a&gt;, and more.&lt;/p&gt;
&lt;p&gt;To learn more, take a look at the
&lt;a href="https://www.pulumi.com/registry/packages/aws/api-docs/"&gt;AWS API documentation&lt;/a&gt;
and the &lt;a href="https://github.com/pulumi/examples/blob/master/aws-ts-resources/index.ts"&gt;sample code that provisions a variety of infrastructure resources&lt;/a&gt;.&lt;/p&gt;</description><author>Donna Malayeri</author><category>javascript</category><category>aws</category></item><item><title>Code, Deploy, and Manage a Serverless REST API on AWS</title><link>https://www.pulumi.com/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/</link><pubDate>Fri, 22 Jun 2018 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/index.png" /&gt;
&lt;p&gt;Pulumi makes it easy to build serverless
applications and connect to other cloud resources. In this blog post,
we&amp;rsquo;ll create a simple REST API that counts the number of times a route
has been hit, using JavaScript to define both the infrastructure and
application code.&lt;/p&gt;
&lt;p&gt;In Pulumi, you define your application infrastructure in regular code,
using JavaScript, Python or Go, and you can target AWS, Azure, Google Cloud, or
Kubernetes. The Pulumi command line tool transforms your into a
declarative plan, following the best practices of immutable
infrastructure. You can write your app code in any language supported by
your serverless platform.&lt;/p&gt;
&lt;h2 id="example-app-serverless-route-counter"&gt;Example app: serverless route counter&lt;/h2&gt;
&lt;p&gt;In this tutorial, we&amp;rsquo;ll build a simple REST API that counts the number
of times a route has been hit. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl $URL/wow
{&amp;quot;route&amp;quot;:&amp;quot;wow&amp;quot;,&amp;quot;count&amp;quot;:1}
$ curl $URL/pulumi
{&amp;quot;route&amp;quot;:&amp;quot;pulumi&amp;quot;,&amp;quot;count&amp;quot;:1}
$ curl $URL/wow
{&amp;quot;route&amp;quot;:&amp;quot;wow&amp;quot;,&amp;quot;count&amp;quot;:2}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&amp;rsquo;ll implement this using API Gateway, Lambda, and Dynamo DB:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/counter-arch.png" alt="counter-arch"&gt;&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;p&gt;If this is your first time using Pulumi, go to &lt;a href="https://app.pulumi.com/signup"&gt;app.pulumi.com&lt;/a&gt; and sign in with
GitHub.&lt;/p&gt;
&lt;p&gt;Then, run the following command to install the Pulumi CLI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl -fsSL https://get.pulumi.com/ | sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&amp;rsquo;re on Windows, run this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@&amp;quot;%SystemRoot%System32WindowsPowerShell1.0powershell.exe&amp;quot; -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command &amp;quot;iex ((New-Object System.Net.WebClient).DownloadString('https://get.pulumi.com/install.ps1'))&amp;quot;
SET &amp;quot;PATH=%PATH%;%USERPROFILE%.pulumiin&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll deploy this app to your own AWS account, so follow the steps to
&lt;a href="https://www.pulumi.com/docs/iac/get-started/aws/"&gt;configure your AWS account&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Make sure you have &lt;a href="https://nodejs.org/en/download/"&gt;Node.js&lt;/a&gt; installed,
with a version of 6.10.x or later.&lt;/p&gt;
&lt;h2 id="create-the-app"&gt;Create the App&lt;/h2&gt;
&lt;p&gt;First we&amp;rsquo;ll create a Pulumi project and add code for both the
infrastructure definitions and application code.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;To create a new Pulumi project, run the following commands:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mkdir hello-http &amp;amp;&amp;amp; cd hello-http
pulumi new aws-javascript
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This creates a new project in the directory &lt;code&gt;hello-http&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the contents of &lt;code&gt;index.js&lt;/code&gt; with the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const cloud = require(&amp;#34;@pulumi/cloud-aws&amp;#34;);
/* Create a mapping from &amp;#39;route&amp;#39; to a count */
let counterTable = new cloud.Table(&amp;#34;counterTable&amp;#34;, &amp;#34;route&amp;#34;);
/* Create an REST API endpoint */
let endpoint = new cloud.API(&amp;#34;hello-world&amp;#34;);
endpoint.get(&amp;#34;/{route+}&amp;#34;, (req, res) =&amp;gt; {
let route = req.params[&amp;#34;route&amp;#34;];
console.log(`Getting count for &amp;#39;${route}&amp;#39;`);
/* get previous value and increment */
/* reference outer counterTable object */
counterTable.get({ route }).then(value =&amp;gt; {
let count = (value &amp;amp;&amp;amp; value.count) || 0;
counterTable.insert({ route, count: ++count }).then(() =&amp;gt; {
res.status(200).json({ route, count });
console.log(`Got count ${count} for &amp;#39;${route}&amp;#39;`);
});
});
});
exports.endpoint = endpoint.publish().url;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The definition for &lt;code&gt;counterTable&lt;/code&gt; stores a counter for each route, using
&lt;code&gt;cloud.Table&lt;/code&gt;. On AWS, this provisions a DynamoDB instance. To create a
new API Gateway instance, we create an instance of &lt;code&gt;cloud.API&lt;/code&gt;. New
routes can be added to this endpoint using functions such as &lt;code&gt;get&lt;/code&gt;,
&lt;code&gt;post&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt; etc.&lt;/p&gt;
&lt;p&gt;The function passed to &lt;code&gt;get&lt;/code&gt; is the interesting part: this becomes the
body of a new AWS Lambda function that is called on a GET request to the
API Gateway. The body of this function can use variables defined in the
main program, such as &lt;code&gt;counterTable&lt;/code&gt;. This is translated to a lookup on
the provisioned DynamoDB instance; there is no need to store the table
name in an environment variable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, add &lt;code&gt;@pulumi/cloud-aws&lt;/code&gt; NPM package:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ npm install --save @pulumi/cloud @pulumi/cloud-aws
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="deploy-the-app"&gt;Deploy the App&lt;/h2&gt;
&lt;p&gt;To deploy both the infrastructure and app code, we&amp;rsquo;ll run
&lt;code&gt;pulumi update&lt;/code&gt;. This command first shows a preview of all the resources
that will be created and prompts for confirmation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/pulumi-update-preview.png" alt="pulumi-update-preview"&gt;&lt;/p&gt;
&lt;p&gt;Choose the &amp;ldquo;yes&amp;rdquo; option to deploy to AWS. At the end of the update,
you&amp;rsquo;ll see a link to the Pulumi Service that shows the details of the
deployment.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/pulumi-update-complete.png" alt="pulumi-update-complete"&gt;&lt;/p&gt;
&lt;p&gt;Go to this link and click the &lt;strong&gt;Resources&lt;/strong&gt; tab. You&amp;rsquo;ll see all the
resources you&amp;rsquo;ve created, including links to the AWS Console.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/code-deploy-and-manage-a-serverless-rest-api-on-aws-with-pulumi/console-resources-tab.png" alt="console-resources-tab"&gt;&lt;/p&gt;
&lt;h2 id="test-the-app"&gt;Test the App&lt;/h2&gt;
&lt;p&gt;Now that the app is deployed, let&amp;rsquo;s try it out! With the Pulumi CLI,
you can easily view output properties for your stack. This line in the
JavaScript code creates a &lt;strong&gt;stack output&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can view stack outputs in the Pulumi Service, or via
&lt;code&gt;pulumi stack output&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pulumi stack output
Current stack outputs (1):
OUTPUT VALUE
endpoint https://5e8xrktey3.execute-api.us-west-2.amazonaws.com/stage/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, let&amp;rsquo;s curl some routes!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl $(pulumi stack output endpoint)/wow
{&amp;quot;route&amp;quot;:&amp;quot;wow&amp;quot;,&amp;quot;count&amp;quot;:1}
$ curl $(pulumi stack output endpoint)/pulumi
{&amp;quot;route&amp;quot;:&amp;quot;pulumi&amp;quot;,&amp;quot;count&amp;quot;:1}
$ curl $(pulumi stack output endpoint)/wow
{&amp;quot;route&amp;quot;:&amp;quot;wow&amp;quot;,&amp;quot;count&amp;quot;:2}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also view logs for the Lambda via &lt;code&gt;pulumi logs&lt;/code&gt;. To get a log
tail, use the &lt;code&gt;--follow&lt;/code&gt; or &lt;code&gt;-f&lt;/code&gt; flag:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pulumi logs
Collecting logs for stack hello-http-dev since 2018-06-15T12:53:35.000-07:00.
2018-06-15T13:52:30.123-07:00[ hello-world4fcc7b60] Getting count for 'wow'
2018-06-15T13:52:34.361-07:00[ hello-world4fcc7b60] Got count 1 for 'wow'
2018-06-15T13:52:39.621-07:00[ hello-world4fcc7b60] Getting count for 'pulumi'
2018-06-15T13:52:39.757-07:00[ hello-world4fcc7b60] Got count 1 for 'pulumi'
2018-06-15T13:52:42.189-07:00[ hello-world4fcc7b60] Getting count for 'wow'
2018-06-15T13:52:42.325-07:00[ hello-world4fcc7b60] Got count 2 for 'wow'
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="clean-up"&gt;Clean up&lt;/h2&gt;
&lt;p&gt;To clean up the resources, run &lt;code&gt;pulumi destroy&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="next-steps"&gt;Next steps&lt;/h2&gt;
&lt;p&gt;The
&lt;a href="https://github.com/pulumi/examples/tree/5f3eae87bb132595e4c60d2d5f8e8ee1473f6a7b/cloud-js-httpserver"&gt;sample code for this application&lt;/a&gt;
is available in the Pulumi examples repo on GitHub. For an end-to-end
TypeScript application with a frontend, see the
&lt;a href="https://github.com/pulumi/examples/tree/5f3eae87bb132595e4c60d2d5f8e8ee1473f6a7b/cloud-ts-url-shortener"&gt;URL shortener sample&lt;/a&gt;.&lt;/p&gt;</description><author>Donna Malayeri</author><category>javascript</category><category>serverless</category><category>aws</category></item><item><title>Build a Video Thumbnailer on AWS</title><link>https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/</link><pubDate>Thu, 21 Jun 2018 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/index.png" /&gt;
&lt;p&gt;Pulumi makes it easy to build cloud applications that use a combination
of containers, lambdas, and connected data services and infrastructure:
Colada apps.&lt;/p&gt;
&lt;p&gt;An example of a Colada app is extracting a thumbnail from a video. A
serverless function can only run for 5 minutes, so we&amp;rsquo;ll run a
container in AWS Fargate to do the video processing.&lt;/p&gt;
&lt;p&gt;In this app, a Lambda function is triggered whenever a new video is
uploaded to S3. This function launches a task in Fargate that
uses &lt;a href="https://www.ffmpeg.org/"&gt;FFmpeg&lt;/a&gt; to extract a video thumbnail. A
second Lambda function is triggered when a new thumbnail has been
created.&lt;/p&gt;
&lt;p&gt;This post was inspired by a blog post from Serverless, Inc that shows
how to combine &lt;a href="https://serverless.com/blog/serverless-application-for-long-running-process-fargate-lambda/"&gt;AWS Fargate and Lambda for a long-running
process&lt;/a&gt;.
Let&amp;rsquo;s see how a similar app would be implemented in Pulumi entirely in
code.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/video-thumbnail-diagram.png" alt="video-thumbnail-diagram"&gt;&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;p&gt;If this is your first time using Pulumi, go
to &lt;a href="https://app.pulumi.com/signup"&gt;https://app.pulumi.com&lt;/a&gt; and sign in with
GitHub.&lt;/p&gt;
&lt;p&gt;Then, run the following command to install the Pulumi CLI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl -fsSL https://get.pulumi.com/ | sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&amp;rsquo;re on Windows, run this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@&amp;quot;%SystemRoot%System32WindowsPowerShell1.0powershell.exe&amp;quot; -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command &amp;quot;iex ((New-Object System.Net.WebClient).DownloadString('https://get.pulumi.com/install.ps1'))&amp;quot;
SET &amp;quot;PATH=%PATH%;%USERPROFILE%.pulumiin&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll deploy this app to your own AWS account, so follow the steps
to &lt;a href="https://www.pulumi.com/registry/packages/aws/installation-configuration/"&gt;configure your AWS account&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Make sure you have &lt;a href="https://nodejs.org/en/download/"&gt;Node.js&lt;/a&gt; installed,
with a version of 6.10.x or later.&lt;/p&gt;
&lt;p&gt;Finally, make sure &lt;a href="https://docs.docker.com/install/"&gt;Docker&lt;/a&gt; is
installed and running.&lt;/p&gt;
&lt;h2 id="create-the-app"&gt;Create the App&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll create a Pulumi project, define the infrastructure and app code
in JavaScript, and create a Dockerfile for the Fargate task.&lt;/p&gt;
&lt;p&gt;First, to create a new Pulumi project, run the following commands:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir hello-colada &amp;amp;&amp;amp; cd hello-colada
pulumi new aws-javascript
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a new project in the &lt;code&gt;hello-colada&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;Second, replace the contents of &lt;code&gt;index.js&lt;/code&gt; with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;@pulumi/cloud-aws&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// A bucket to store videos and thumbnails.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucketName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// A task which runs a containerized FFMPEG job to extract a thumbnail image.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ffmpegThumbnailTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ffmpegThumbTask&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// folder containing the Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;memoryReservation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// When a new video is uploaded, run the FFMPEG task on the video file.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Use the time index specified in the filename (e.g. cat_00-01.mp4 uses timestamp 00:01)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onPut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;onNewVideo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucketArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`*** New video: file &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;bucketArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; was uploaded at &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;bucketArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventTime&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucketArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thumbnailFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;framePos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ffmpegThumbnailTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;S3_BUCKET&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bucketName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;INPUT_VIDEO&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;TIME_OFFSET&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;framePos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;OUTPUT_FILE&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;thumbnailFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Running thumbnailer task.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;keySuffix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;.mp4&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// When a new thumbnail is created, log a message.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onPut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;onNewThumbnail&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucketArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`*** New thumbnail: file &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;bucketArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; was saved at &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;bucketArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventTime&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;keySuffix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Export the bucket name.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucketName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucketName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code uses &lt;code&gt;cloud.Task&lt;/code&gt;, a high-level, convenient component for
working with containers. The component automatically provisions a
container registry instance in ECR, runs a Docker build, and saves the
Docker image to the provisioned ECR instance. It also defines an ECS
task and configures it to use the built image. All this in just 4 lines
of code!&lt;/p&gt;
&lt;p&gt;Next, in the same directory, create a &lt;code&gt;Dockerfile&lt;/code&gt; with the following
contents. We&amp;rsquo;ll use an existing FFmpeg container and install the AWS
CLI. When the container is started, it copies the video file from S3,
runs &lt;code&gt;ffmpeg&lt;/code&gt;, and copies the output back to S3.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; FROM jrottenberg/ffmpeg
RUN apt-get update &amp;amp;&amp;amp;
apt-get install python-dev python-pip -y &amp;amp;&amp;amp;
apt-get clean
RUN pip install awscli
WORKDIR /tmp/workdir
ENTRYPOINT
echo &amp;quot;Starting ffmpeg task...&amp;quot; &amp;amp;&amp;amp;
echo &amp;quot;Copying video from S3&amp;quot; &amp;amp;&amp;amp;
aws s3 cp s3://${S3_BUCKET}/${INPUT_VIDEO} ./${INPUT_VIDEO} &amp;amp;&amp;amp;
ffmpeg -v error -i ./${INPUT_VIDEO} -ss ${TIME_OFFSET} -vframes 1 -f image2 -an -y ${OUTPUT_FILE} &amp;amp;&amp;amp;
echo &amp;quot;Copying thumbnail to S3&amp;quot; &amp;amp;&amp;amp;
aws s3 cp ./${OUTPUT_FILE} s3://${S3_BUCKET}/${OUTPUT_FILE}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Install the &lt;code&gt;@pulumi/cloud-aws&lt;/code&gt; NPM package:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ npm install --save @pulumi/cloud-aws @pulumi/cloud
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, configure Pulumi to use AWS Fargate. Note that, currently,
Fargate is available only in &lt;code&gt;us-east-1&lt;/code&gt;, &lt;code&gt;us-east-2&lt;/code&gt;, &lt;code&gt;us-west-2&lt;/code&gt;,
and &lt;code&gt;eu-west-1&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pulumi config set cloud-aws:useFargate true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it! Now, let&amp;rsquo;s deploy the app.&lt;/p&gt;
&lt;h2 id="deploy-the-app"&gt;Deploy the App&lt;/h2&gt;
&lt;p&gt;To deploy both the infrastructure and app code, we&amp;rsquo;ll
run &lt;code&gt;pulumi update&lt;/code&gt;. This command first shows a preview of all the
resources that will be created and prompts for confirmation. During the
preview phase, Pulumi invokes &lt;code&gt;docker build&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Choose the &amp;ldquo;yes&amp;rdquo; option to deploy to AWS. This will take about 5
minutes. Pulumi automatically builds and provisions an AWS container
repository in ECR, builds the Docker container, and places the image in
the repository. This all happens automatically and does not require
manual configuration on your part.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/pulumi-update-output.png" alt="pulumi-update-output"&gt;&lt;/p&gt;
&lt;p&gt;At the end of the update, you&amp;rsquo;ll see a link to the Pulumi Service that
shows the details of the deployment.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/pulumi-update-complete-1.png" alt="pulumi-update-complete-1"&gt;&lt;/p&gt;
&lt;p&gt;Go to the &lt;strong&gt;Resources&lt;/strong&gt; tab and filter to S3 resources. Then, on the S3
bucket, click the link to go to the AWS Console.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/console-s3-filtered.png" alt="console-s3-filtered"&gt;&lt;/p&gt;
&lt;h2 id="upload-a-video"&gt;Upload a Video&lt;/h2&gt;
&lt;p&gt;Upload an .mp4 video to your S3 bucket, making sure to encode the
desired time index in the filename. For instance,
use &lt;code&gt;myvideo_00-02.mp4&lt;/code&gt; to extract the frame at 0 minutes and 2 seconds.&lt;/p&gt;
&lt;p&gt;You can &lt;a href="https://github.com/pulumi/examples"&gt;use this video of my cat&lt;/a&gt;,
which you should save as &lt;code&gt;cat_00-01.mp4&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Upload this video in the S3 console. Or, use the AWS CLI along with
the &lt;code&gt;pulumi stack output&lt;/code&gt; command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ aws s3 cp cat_00-01.mp4 s3://$(pulumi stack output bucketName)
upload: cat_00-01.mp4 to s3://bucket-3a4f226/cat_00-01.mp4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To see what the app is doing, use the &lt;code&gt;pulumi logs&lt;/code&gt; command, with
the &lt;code&gt;--follow&lt;/code&gt; or &lt;code&gt;-f&lt;/code&gt; parameter. This command aggregates all the logs
for your compute, so the logs for the Lambda function &lt;strong&gt;and&lt;/strong&gt; the
Fargate task are all in one place!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/build-a-video-thumbnailer-with-pulumi-using-lambdas-containers-and-infrastructure-on-aws/terminal-logs.png" alt="terminal-logs"&gt;&lt;/p&gt;
&lt;p&gt;Once the thumbnail has been generated, either view it in the S3 console,
or download it with the AWS CLI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ aws s3 cp s3://$(pulumi stack output bucketName)/cat.jpg .
download: s3://bucket-0c91106/cat.jpg to ./cat.jpg
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="clean-up"&gt;Clean Up&lt;/h2&gt;
&lt;p&gt;To clean up the resources we&amp;rsquo;ve provisioned, run &lt;code&gt;pulumi destroy&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="next-steps"&gt;Next Steps&lt;/h3&gt;
&lt;p&gt;In this post, we saw how easy it is to use containers and serverless
functions in one application. With Pulumi, you get the best of both
worlds, and don&amp;rsquo;t have to choose one or the other.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/pulumi/examples"&gt;sample code for this post&lt;/a&gt; is
available in the &lt;a href="https://github.com/pulumi/examples"&gt;Pulumi examples repo on
GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For a version of this sample that includes AWS Rekognition, see
the &lt;a href="https://github.com/pulumi/examples"&gt;Video Thumbnailer with Machine Learning&lt;/a&gt; JavaScript
example.&lt;/p&gt;</description><author>Donna Malayeri</author><category>javascript</category><category>serverless</category><category>aws</category><category>containers</category></item><item><title>Deploying production-ready containers with Pulumi</title><link>https://www.pulumi.com/blog/deploying-production-ready-containers-with-pulumi/</link><pubDate>Wed, 20 Jun 2018 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/deploying-production-ready-containers-with-pulumi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/deploying-production-ready-containers-with-pulumi/index.png" /&gt;
&lt;p&gt;Containers are a great way to deploy applications to the cloud,
especially with new execution models like &lt;a href="https://aws.amazon.com/fargate/"&gt;AWS
Fargate&lt;/a&gt;. Pulumi makes it easy to
deploy production Docker containers, handling details such as creating a
container registry instance in ECR, creating task definitions in ECS,
and configuring a load balancer. With Pulumi, deploying a container to
production is almost as easy as running it locally!&lt;/p&gt;
&lt;p&gt;In this blog post, we&amp;rsquo;ll deploy a simple Docker container running
NGINX.&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;p&gt;If this is your first time using Pulumi, go to
&lt;a href="https://app.pulumi.com/signup"&gt;https://app.pulumi.com&lt;/a&gt; and sign in with
GitHub.&lt;/p&gt;
&lt;p&gt;Then, run the following command to install the Pulumi CLI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl -fsSL https://get.pulumi.com/ | sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&amp;rsquo;re on Windows, run this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@&amp;quot;%SystemRoot%System32WindowsPowerShell1.0powershell.exe&amp;quot; -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command &amp;quot;iex ((New-Object System.Net.WebClient).DownloadString('https://get.pulumi.com/install.ps1'))&amp;quot;
SET &amp;quot;PATH=%PATH%;%USERPROFILE%.pulumiin&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll deploy this app to your own AWS account, so follow the steps to
&lt;a href="https://www.pulumi.com/registry/packages/aws/installation-configuration/"&gt;configure your AWS account&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Make sure you have &lt;a href="https://nodejs.org/en/download/"&gt;Node.js&lt;/a&gt; installed,
with a version of 6.10.x or later.&lt;/p&gt;
&lt;p&gt;Finally, make sure &lt;a href="https://docs.docker.com/install/"&gt;Docker&lt;/a&gt; is
installed and running.&lt;/p&gt;
&lt;h2 id="create-the-app"&gt;Create the app&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll create a Pulumi project, define the infrastructure in JavaScript,
and create a Dockerfile.&lt;/p&gt;
&lt;p&gt;To create a new Pulumi project, run the following commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir hello-containers &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; hello-containers
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi new aws-javascript
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This creates a new project in the directory &lt;code&gt;hello-containers&lt;/code&gt;. Next, replace the contents of &lt;code&gt;index.js&lt;/code&gt; with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;@pulumi/cloud-aws&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pulumi-nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;containers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;ports&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* export just the hostname property of the container frontend */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultEndpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sb"&gt;`http://&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These 15 lines of code are everything you need to deploy a custom
container! We&amp;rsquo;re using &lt;code&gt;cloud.Service&lt;/code&gt;, which is a high-level,
convenient interface for building containers and provisioning an AWS
container service. Using the &lt;code&gt;build&lt;/code&gt; property, we point to a folder
containing a &lt;code&gt;Dockerfile&lt;/code&gt;, which is &lt;code&gt;app&lt;/code&gt; in this case.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s create a &lt;code&gt;Dockerfile&lt;/code&gt; and a static page. Create a
subfolder &lt;code&gt;app&lt;/code&gt; with the following files.&lt;/p&gt;
&lt;p&gt;Add the following as &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;FROM nginx
COPY index.html /usr/share/nginx/html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Add the following as &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello containers!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Made with ❤️ with &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://pulumi.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pulumi&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should have the following directory structure:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/deploying-production-ready-containers-with-pulumi/file-layout.png" alt="file layout"&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the &lt;code&gt;@pulumi/cloud-aws&lt;/code&gt; NPM package:&lt;/p&gt;
&lt;p&gt;npm install &amp;ndash;save @pulumi/cloud-aws @pulumi/cloud&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure Pulumi to use AWS Fargate. Note that, currently, Fargate is
available only in &lt;code&gt;us-east-1&lt;/code&gt;, &lt;code&gt;us-east-2&lt;/code&gt;, &lt;code&gt;us-west-2&lt;/code&gt;, and
&lt;code&gt;eu-west-1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;pulumi config set cloud-aws:useFargate true&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="deploy-the-app"&gt;Deploy the app&lt;/h2&gt;
&lt;p&gt;To deploy both the infrastructure and app code, we&amp;rsquo;ll run
&lt;code&gt;pulumi update&lt;/code&gt;. This command first shows a preview of all the resources
that will be created and prompts for confirmation. During the preview
phase, Pulumi invokes &lt;code&gt;docker build&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/deploying-production-ready-containers-with-pulumi/pulumi-update-preview.png" alt="Pulumi preview"&gt;&lt;/p&gt;
&lt;p&gt;Choose the &lt;code&gt;yes&lt;/code&gt; option to deploy to AWS. This will take about 5
minutes. Pulumi automatically builds and provisions an AWS container
repository in ECR, builds the Docker container, and places the image in
the repository. This all happens automatically and does not require
manual configuration on your part.&lt;/p&gt;
&lt;p&gt;At the end of the update, you&amp;rsquo;ll see a link to the Pulumi Service that
shows the details of the deployment.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/deploying-production-ready-containers-with-pulumi/update-complete.png" alt="update complete"&gt;&lt;/p&gt;
&lt;p&gt;Go to this link and click the &lt;strong&gt;Resources&lt;/strong&gt; tab. You&amp;rsquo;ll see all the
resources you&amp;rsquo;ve created. Notice that Pulumi has created an ECR
repository, a load balancer, an ECS service and task definition, and IAM
roles.&lt;/p&gt;
&lt;p&gt;Now, go back to the stack details page, which shows the stack
configuration, as well as the stack output property. The following line
creates the stack output &lt;code&gt;url&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exports.url = service.defaultEndpoint.apply(e =&amp;gt; `http://${e.hostname}`);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you navigate to the link for &lt;code&gt;url&lt;/code&gt; you&amp;rsquo;ll see the following page:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/deploying-production-ready-containers-with-pulumi/hello-world-page.png" alt="&amp;ldquo;Hello, World!&amp;rdquo;"&gt;&lt;/p&gt;
&lt;h2 id="view-logs"&gt;View logs&lt;/h2&gt;
&lt;p&gt;You can view container frontend and compute logs via the &lt;code&gt;pulumi logs&lt;/code&gt;
command. You can see here that most of the traffic is hitting routes
that don&amp;rsquo;t exist, aside from the last log line where I navigated to the
site using Chrome. Since this is an HTTP server that&amp;rsquo;s open to the
internet, it&amp;rsquo;s not uncommon for attackers to try to find a security
vulnerability on a site. Fortunately, our container is serving only
static content. The logs command makes it easy to get details on your
site traffic.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pulumi logs
Collecting logs for stack hello-containers-dev since 2018-06-15T15:01:18.000-07:00.
2018-06-15T15:27:47.468-07:00[ pulumi-nginx] 2018/06/15 22:27:47 [error] 5#5: *4 open() &amp;quot;/usr/share/nginx/html/proxychecker.axd&amp;quot; failed (2: No such file or directory), client: 62.210.157.152, server: localhost, request: &amp;quot;GET http://proxy.dazhou.net/proxychecker.axd?e=457758511%40qq.com&amp;amp;p=http%3A%2F%2F34.201.27.186%3A80&amp;amp;s=AS HTTP/1.1&amp;quot;, host: &amp;quot;proxy.dazhou.net&amp;quot;
2018-06-15T15:27:47.468-07:00[ pulumi-nginx] 62.210.157.152 - - [15/Jun/2018:22:27:47 +0000] &amp;quot;GET http://proxy.dazhou.net/proxychecker.axd?e=457758511%40qq.com&amp;amp;p=http%3A%2F%2F34.201.27.186%3A80&amp;amp;s=AS HTTP/1.1&amp;quot; 404 170 &amp;quot;-&amp;quot; &amp;quot;Go-http-client/1.1&amp;quot; &amp;quot;-&amp;quot;
2018-06-15T15:32:02.128-07:00[ pulumi-nginx] 2018/06/15 22:32:02 [error] 5#5: *382 &amp;quot;/usr/share/nginx/html/phpmyadmin/index.html&amp;quot; is not found (2: No such file or directory), client: 178.239.177.212, server: localhost, request: &amp;quot;HEAD http://34.201.27.186:80/phpmyadmin/ HTTP/1.1&amp;quot;, host: &amp;quot;34.201.27.186&amp;quot;
2018-06-15T16:07:05.874-07:00[ pulumi-nginx] 172.31.44.144 - - [15/Jun/2018:23:07:05 +0000] &amp;quot;GET / HTTP/1.1&amp;quot; 304 0 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36&amp;quot; &amp;quot;-&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="clean-up"&gt;Clean up&lt;/h2&gt;
&lt;p&gt;To clean up the resources we&amp;rsquo;ve provisioned, run &lt;code&gt;pulumi destroy&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="next-steps"&gt;Next steps&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://github.com/pulumi/examples/tree/5f3eae87bb132595e4c60d2d5f8e8ee1473f6a7b/cloud-js-containers"&gt;sample code for this post&lt;/a&gt;
is available in the &lt;a href="https://github.com/pulumi/examples"&gt;Pulumi examples repo on GitHub&lt;/a&gt;. For an example application
that connects two containers, see the &lt;a href="https://github.com/pulumi/examples/tree/5f3eae87bb132595e4c60d2d5f8e8ee1473f6a7b/cloud-ts-voting-app"&gt;Voting App&lt;/a&gt;
TypeScript sample.&lt;/p&gt;</description><author>Donna Malayeri</author><category>javascript</category><category>aws</category><category>containers</category></item></channel></rss>