Deploying a Playwright Container using Docker in AWS

Post by
Andrew Pierno
Deploying a Playwright Container using Docker in AWS

Prerequisites

Before we begin, make sure you have the following installed:

Creating the Dockerfile

First, let's create a Dockerfile in the root of your project. This file will contain instructions for building our container image.

# Use the official Playwright image as our base image
FROM mcr.microsoft.com/playwright:v1.14.0-focal
# Set the working directory
WORKDIR /app
# Copy package.json and package-lock.json to the working directory
COPY package.json package-lock.json ./
# Install dependencies
RUN npm ci
# Copy the rest of the application code to the working directory
COPY . .
# Expose the port the app will run on
EXPOSE 3000
# Start the application
CMD ["npm", "start"]

This Dockerfile uses the official Playwright image as the base image, sets the working directory to /app, installs the dependencies, and finally starts the application.

Alternatively, you can install the required dependencies on your own. In the example below, we are using the node alpine image which is a lightweight version of the Node.js runtime environment available for Docker. The alpine image is based on Alpine Linux designed for containers. This image is perfect for applications that require minimal overhead for their runtime environments, as it has a small footprint with a minimal set of tools installed.

# Use the official Node.js 14 image as a base
FROM node:14-alpine3.17
# Install the necessary dependencies for the browser binaries
RUN apk add --no-cache \
   udev \
   ttf-freefont \
   font-noto \
   chromium \
   nss \
   freetype \
   freetype-dev \
   harfbuzz \
   ca-certificates \
   lcms2-dev \
   libpng-dev \
   libjpeg-turbo-dev \
   libwebp-dev \
   zlib-dev \
   libxcomposite \
   libxcursor \
   libxdamage \
   libxext \
   libxi \
   libxrandr \
   libxscrnsaver \
   libxkbcommon \
   libxshmfence \
   libxxf86vm \
   mesa-gl \
   mesa-dri-gallium
   
# Set environment variables for Playwright browsers
ENV PLAYWRIGHT_BROWSERS_PATH=/usr/src/app/node_modules/playwright/.local-browsers
ENV CHROMIUM_BIN=/usr/bin/chromium-browser
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Install Playwright browsers
RUN npx playwright install
# Bundle app source
COPY . /usr/src/app
# Expose the application port
EXPOSE 3000
# Start the application
CMD [ "npm", "start" ]

Building the Docker image

Next, let's build the Docker image using the following command:

docker build -t your-image-name .

If you’re using a M1 mac and planning to deploy on amd 64 based architecture (Amazon linux in our case)

You can build the image using the following command

docker buildx build --platform=linux/amd64 -t your-image-name .

Replace your-image-name with the name you want to give your container image.

Pushing the Docker image to Amazon ECR

Now we'll push our Docker image to Amazon Elastic Container Registry (ECR) so that we can deploy it to ECS.

First, create a new repository in ECR:

aws ecr create-repository --repository-name your-repo-name

Replace your-repo-name with the name you want to give your ECR repository.

Next, log in to ECR using the AWS CLI:

aws ecr get-login-password --region your-region | docker login --username AWS --password-stdin your-account-id.dkr.ecr.your-region.amazonaws.com

Replace your-region with your AWS region, and your-account-id with your AWS account ID.

Now, tag your Docker image with the ECR repository URI:

docker tag your-image-name:latest your-account-id.dkr.ecr.your-region.amazonaws.com/your-repo-name:latest

Finally, push the Docker image to ECR:

docker push your-account-id.dkr.ecr.your-region.amazonaws.com/your-repo-name:latest

Deploying the Docker container to Amazon ECS

Now that our Docker image is in ECR, we can deploy it to ECS.

First, create an ECS cluster:

aws ecs create-cluster --cluster-name your-cluster-name

Replace your-cluster-name with the name you want to give your ECS cluster.

Next, create a task definition for your container. Save the following JSON to a file called task-definition.json:

{
 "family": "your-task-definition-name",
 "containerDefinitions": [
   {
     "name": "your-container-name",
     "image": "your-account-id.dkr.ecr.your-region.amazonaws.com/your-repo-name:latest",
     "portMappings": [
       {
         "containerPort": 3000
       }
     ],
     "essential": true
   }
 ],
 "requiresCompatibilities": ["FARGATE"],
 "networkMode": "awsvpc",
 "cpu": "256",
 "memory": "512"
}

Replace your-task-definition-name with the name you want to give your task definition, your-container-name with the name you want to give your container, your-account-id with your AWS account ID, and your-region with your AWS region.

Now, register the task definition with ECS:

aws ecs register-task-definition --cli-input-json file://task-definition.json

Finally, create a service to run your container:

aws ecs create-service --cluster your-cluster-name --service-name your-service-name --task-definition your-task-definition-name --desired-count 1 --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[your-subnet-id],securityGroups=[your-security-group-id]}"

Replace your-cluster-name with the name of your ECS cluster, your-service-name with the name you want to give your service, your-task-definition-name with the name of your task definition, your-subnet-id with the ID of your VPC subnet, and your-security-group-id with the ID of your security group.

Your Playwright container should now be running in ECS. You can view the logs and monitor the status of your container using the AWS Management Console.

Conclusion

In this tutorial, we've learned how to deploy a Playwright container using Docker in AWS. This allows us to run our Playwright tests in a scalable, cloud-based environment. By deploying our container to Amazon ECS, we can easily scale our tests to handle increased load and take advantage of AWS's robust infrastructure.

Handling something as resource-intensive as playwright can be painful. Try screenshotapi instead, which is a reliable solution for taking screenshots or generating PDFs of any website in seconds.