DEV Community

ぎゃばん
ぎゃばん

Posted on

Amazon Linux 2でHeadless Chromeを動かす

Amazon Linuxでは、GUI向けのパッケージが提供されていませんでした。Headless Chromeはlibgtk3に依存しており、Amazon Linuxにlibgtk3をインストールするのに大変な手間が必要でした。 Amazon Linux 2になり、GUI向けのパッケージが提供され、Red Hat Enterprise Linux 7.4とほとんど変わらない手順でHeadless Chromeを動かせるようになりました。

Amazon Linux 2にHeadless Chromeをインストールしてみましょう。

EC2インスタンス 作成

Amazon Linux 2でAWS EC2インスタンスを作成します。

事前条件

AWSコマンドの設定が終わっているものとします。

  • キーペア chromium-on-amazon-linux2
  • SSH接続可能なセキュリティグループ sg-77d46f0e

があるとします。

EC2インスタンス 作成

aws ec2 run-instances --image-id ami-2a34b64c --count 1 --instance-type t2.micro --key-name chromium-on-amazon-linux2 --security-group-ids sg-77d46f0e
{
    "Groups": [],
    "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-2a34b64c",
            "InstanceId": "i-0f3efae9b9002b82e",
            "InstanceType": "t2.micro",
            "KeyName": "chromium-on-amazon-linux2",
            "LaunchTime": "2018-01-10T06:11:19.000Z",
            "Monitoring": {
                "State": "disabled"
            },
            "Placement": {
                "AvailabilityZone": "ap-northeast-1a",
                "GroupName": "",
                "Tenancy": "default"
            },
            "PrivateDnsName": "ip-172-31-6-102.ap-northeast-1.compute.internal",
            "PrivateIpAddress": "172.31.6.102",
            "ProductCodes": [],
            "PublicDnsName": "",
            "State": {
                "Code": 0,
                "Name": "pending"
            },
            "StateTransitionReason": "",
            "SubnetId": "subnet-6bca3b1c",
            "VpcId": "vpc-4c30c129",
            "Architecture": "x86_64",
            "BlockDeviceMappings": [],
            "ClientToken": "",
            "EbsOptimized": false,
            "Hypervisor": "xen",
            "NetworkInterfaces": [
                {
                    "Attachment": {
                        "AttachTime": "2018-01-10T06:11:19.000Z",
                        "AttachmentId": "eni-attach-a2db2748",
                        "DeleteOnTermination": true,
                        "DeviceIndex": 0,
                        "Status": "attaching"
                    },
                    "Description": "",
                    "Groups": [
                        {
                            "GroupName": "launch-wizard-1",
                            "GroupId": "sg-77d46f0e"
                        }
                    ],
                    "Ipv6Addresses": [],
                    "MacAddress": "06:31:39:4b:07:38",
                    "NetworkInterfaceId": "eni-e98d92d5",
                    "OwnerId": "016753510962",
                    "PrivateDnsName": "ip-172-31-6-102.ap-northeast-1.compute.internal",
                    "PrivateIpAddress": "172.31.6.102",
                    "PrivateIpAddresses": [
                        {
                            "Primary": true,
                            "PrivateDnsName": "ip-172-31-6-102.ap-northeast-1.compute.internal",
                            "PrivateIpAddress": "172.31.6.102"
                        }
                    ],
                    "SourceDestCheck": true,
                    "Status": "in-use",
                    "SubnetId": "subnet-6bca3b1c",
                    "VpcId": "vpc-4c30c129"
                }
            ],
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SecurityGroups": [
                {
                    "GroupName": "launch-wizard-1",
                    "GroupId": "sg-77d46f0e"
                }
            ],
            "SourceDestCheck": true,
            "StateReason": {
                "Code": "pending",
                "Message": "pending"
            },
            "VirtualizationType": "hvm"
        }
    ],
    "OwnerId": "016753510962",
    "ReservationId": "r-0d34db4dcac25c65f"
}

次に生成されたEC2インスタンスにSSHでログインします。

SSH ログイン

PublicIpAddressはEC2インスタンス生成と同時には取得できません。
InstanceIdの値を使って、PublicIpAddressを取得します。

aws ec2 describe-instances --instance-ids i-0f3efae9b9002b82e
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "ami-2a34b64c",
                    "InstanceId": "i-0f3efae9b9002b82e",
                    "InstanceType": "t2.micro",
                    "KeyName": "chromium-on-amazon-linux2",
                    "LaunchTime": "2018-01-10T06:11:19.000Z",
                    "Monitoring": {
                        "State": "disabled"
                    },
                    "Placement": {
                        "AvailabilityZone": "ap-northeast-1a",
                        "GroupName": "",
                        "Tenancy": "default"
                    },
                    "PrivateDnsName": "ip-172-31-6-102.ap-northeast-1.compute.internal",
                    "PrivateIpAddress": "172.31.6.102",
                    "ProductCodes": [],
                    "PublicDnsName": "ec2-13-230-156-244.ap-northeast-1.compute.amazonaws.com",
                    "PublicIpAddress": "13.230.156.244",
                    "State": {
                        "Code": 16,
                        "Name": "running"
                    },
                    "StateTransitionReason": "",
                    "SubnetId": "subnet-6bca3b1c",
                    "VpcId": "vpc-4c30c129",
                    "Architecture": "x86_64",
                    "BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda",
                            "Ebs": {
                                "AttachTime": "2018-01-10T06:11:20.000Z",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-068a21bf8110a0b90"
                            }
                        }
                    ],
                    "ClientToken": "",
                    "EbsOptimized": false,
                    "EnaSupport": true,
                    "Hypervisor": "xen",
                    "NetworkInterfaces": [
                        {
                            "Association": {
                                "IpOwnerId": "amazon",
                                "PublicDnsName": "ec2-13-230-156-244.ap-northeast-1.compute.amazonaws.com",
                                "PublicIp": "13.230.156.244"
                            },
                            "Attachment": {
                                "AttachTime": "2018-01-10T06:11:19.000Z",
                                "AttachmentId": "eni-attach-a2db2748",
                                "DeleteOnTermination": true,
                                "DeviceIndex": 0,
                                "Status": "attached"
                            },
                            "Description": "",
                            "Groups": [
                                {
                                    "GroupName": "launch-wizard-1",
                                    "GroupId": "sg-77d46f0e"
                                }
                            ],
                            "Ipv6Addresses": [],
                            "MacAddress": "06:31:39:4b:07:38",
                            "NetworkInterfaceId": "eni-e98d92d5",
                            "OwnerId": "016753510962",
                            "PrivateDnsName": "ip-172-31-6-102.ap-northeast-1.compute.internal",
                            "PrivateIpAddress": "172.31.6.102",
                            "PrivateIpAddresses": [
                                {
                                    "Association": {
                                        "IpOwnerId": "amazon",
                                        "PublicDnsName": "ec2-13-230-156-244.ap-northeast-1.compute.amazonaws.com",
                                        "PublicIp": "13.230.156.244"
                                    },
                                    "Primary": true,
                                    "PrivateDnsName": "ip-172-31-6-102.ap-northeast-1.compute.internal",
                                    "PrivateIpAddress": "172.31.6.102"
                                }
                            ],
                            "SourceDestCheck": true,
                            "Status": "in-use",
                            "SubnetId": "subnet-6bca3b1c",
                            "VpcId": "vpc-4c30c129"
                        }
                    ],
                    "RootDeviceName": "/dev/xvda",
                    "RootDeviceType": "ebs",
                    "SecurityGroups": [
                        {
                            "GroupName": "launch-wizard-1",
                            "GroupId": "sg-77d46f0e"
                        }
                    ],
                    "SourceDestCheck": true,
                    "VirtualizationType": "hvm"
                }
            ],
            "OwnerId": "016753510962",
            "ReservationId": "r-0d34db4dcac25c65f"
        }
    ]
}
ssh -i chromium-on-amazon-linux2.pem ec2-user@13.230.156.244

依存パッケージインストール

yumパッケージを更新します。

sudo yum update -y

Chromiumが依存するパッケージをインストールします。

sudo yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y

この部分が今までのAmazon Linuxで実現しようとすると、大変な手間が掛かっていました。Amazon Linux 2では設定なしで、yumコマンドでインストールできます。
参考:Installing Google Chrome On CentOS, Amazon Linux, or RHEL

Chromiumインストール

ここから少しズルをします。
GoogleChrome/puppeteer: Headless Chrome Node APIはインストール時に、自動的にChromiumのバイナリをダウンロードします。
これを使います。

Node.jsインストール

curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
sudo yum -y install nodejs

puppeteerインストール

npm init -y
npm i puppeteer

動作確認

次の内容のindex.jsを作ります。

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');

  // Get the "viewport" of the page, as reported by the page.
  const dimensions = await page.evaluate(() => {
    return {
      width: document.documentElement.clientWidth,
      height: document.documentElement.clientHeight,
      deviceScaleFactor: window.devicePixelRatio
    };
  });

  console.log('Dimensions:', dimensions);

  await browser.close();
})();
node .

で、実行します。

Dimensions: { width: 800, height: 600, deviceScaleFactor: 1 }

が表示されれば成功です!!

後始末

使い終わったEC2インスタンスを削除します。

aws ec2 terminate-instances --instance-ids i-0f3efae9b9002b82e

Top comments (0)