<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mathew</title>
    <description>The latest articles on DEV Community by Mathew (@mathew).</description>
    <link>https://dev.to/mathew</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F656944%2F77518ca7-264d-40a7-9e5e-83bb43404f3d.png</url>
      <title>DEV Community: Mathew</title>
      <link>https://dev.to/mathew</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mathew"/>
    <language>en</language>
    <item>
      <title>Debugging Node.js applications running on ECS Fargate</title>
      <dc:creator>Mathew</dc:creator>
      <pubDate>Sat, 14 Aug 2021 09:03:38 +0000</pubDate>
      <link>https://dev.to/mathew/debugging-node-js-applications-running-on-ecs-fargate-56cn</link>
      <guid>https://dev.to/mathew/debugging-node-js-applications-running-on-ecs-fargate-56cn</guid>
      <description>&lt;p&gt;AWS Fargate is a serverless compute engine for containers. It removes the need to provision and manage servers. To know more on Fargate, you can visit &lt;a href="https://aws.amazon.com/fargate/?nc=sn&amp;amp;loc=1"&gt;this page&lt;/a&gt;.&lt;br&gt;
In this blog post, we will see how to debug a Node.js application running on ECS Fargate using the new ECS Exec feature. Once this is done, you'll be able to debug your application using Chrome DevTools. I used this to debug memory leaks in a Node.js application.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SSH and Google Chrome installed (to create SSH tunnel).&lt;/li&gt;
&lt;li&gt;A SSH key pair (public key and private key). I used PuTTYgen to generate and save these keys.&lt;/li&gt;
&lt;li&gt;AWS CLI configured.&lt;/li&gt;
&lt;li&gt;AWS Systems Manager Session Manager plugin installed.&lt;/li&gt;
&lt;li&gt;Node.js application running in ECS Fargate.&lt;/li&gt;
&lt;li&gt;ECS service's security group has ports 22 and 9229 open in inbound rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll use SSH tunnel to establish connection between the Fargate server and the local system.&lt;/p&gt;
&lt;h2&gt;
  
  
  AWS Configurations
&lt;/h2&gt;

&lt;p&gt;Considering that you have a task already running in ECS Fargate, the next step is to enable debugging for the application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Enable Debugging Mode
&lt;/h3&gt;

&lt;p&gt;When enabled, the Node.js process listens for a debugging client on port 9229. To enable this, you have to add &lt;code&gt;--inspect&lt;/code&gt; when running the application. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node server.js &lt;span class="nt"&gt;--inspect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enable ECS Exec Feature
&lt;/h3&gt;

&lt;p&gt;Open the ECS Task role in IAM and add below policy to the role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:CreateControlChannel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:CreateDataChannel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:OpenControlChannel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:OpenDataChannel"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we run the AWS CLI command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecs update-service &lt;span class="nt"&gt;--service&lt;/span&gt; &amp;lt;service-name&amp;gt; &lt;span class="nt"&gt;--cluster&lt;/span&gt; &amp;lt;cluster-name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; &amp;lt;region&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--enable-execute-command&lt;/span&gt; &lt;span class="nt"&gt;--force-new-deployment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the content inside angular brackets with appropriate values.&lt;/p&gt;

&lt;p&gt;Once the above command is executed, a new task will start with ECS Exec enabled. If you receive any error when running the above command, please check the error response you received and try to resolve it. You can find troubleshooting tips from AWS docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install requirements in the ECS task
&lt;/h3&gt;

&lt;p&gt;Now we can ECS Exec into the running task and configure SSH. Use the below command to exec into the ECS task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecs execute-command &lt;span class="nt"&gt;--cluster&lt;/span&gt; &amp;lt;cluster-name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--task&lt;/span&gt; &amp;lt;task-id&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--container&lt;/span&gt; &amp;lt;container-name-to-execute-the-command-on&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--interactive&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--command&lt;/span&gt; &lt;span class="s2"&gt;"/bin/sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be getting an interactive session in the Fargate server. Next, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt-get update
apt-get &lt;span class="nb"&gt;install &lt;/span&gt;openssh-server &lt;span class="nt"&gt;-y&lt;/span&gt;
service ssh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you'll have SSH server running in the ECS task.&lt;br&gt;
We'll have to do a few more steps to get this working right. Create a file called &lt;code&gt;docker-entrypoint.sh&lt;/code&gt; and paste below code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nv"&gt;SSH_PUBLIC_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;ssh-public-key&amp;gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSH_PUBLIC_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Need your SSH public key"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="c"&gt;# Create a folder to store user's SSH keys if it does not exist.&lt;/span&gt;
&lt;span class="nv"&gt;USER_SSH_KEYS_FOLDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.ssh
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$USER_SSH_KEYS_FOLDER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$USER_SSH_KEYS_FOLDER&lt;/span&gt;

&lt;span class="c"&gt;# Copy contents from the `SSH_PUBLIC_KEY` variable&lt;/span&gt;
&lt;span class="c"&gt;# to the `${USER_SSH_KEYS_FOLDER}/authorized_keys` file.&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SSH_PUBLIC_KEY&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER_SSH_KEYS_FOLDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/authorized_keys

&lt;span class="c"&gt;# Clear the `SSH_PUBLIC_KEY` variable.&lt;/span&gt;
&lt;span class="nb"&gt;unset &lt;/span&gt;SSH_PUBLIC_KEY

&lt;span class="c"&gt;# Start the SSH daemon.&lt;/span&gt;
/usr/sbin/sshd &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Success"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;ssh-public-key&amp;gt;&lt;/code&gt; with the SSH public key you generated earlier. Now save the file.&lt;br&gt;
So far so good. Next, run the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x docker-entrypoint.sh 
./docker-entrypoint.sh 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we come back to our local system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local System Configurations
&lt;/h2&gt;

&lt;p&gt;Go to the directory where the SSH private key is stored and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;700 ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test the SSH connection, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@&amp;lt;ecs-task-ip&amp;gt; &lt;span class="nt"&gt;-i&lt;/span&gt; ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally run the command to create the SSH tunnel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-nNT&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 9229:127.0.0.1:9229 root@&amp;lt;ecs-task-ip&amp;gt; &lt;span class="nt"&gt;-i&lt;/span&gt; ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should do it!&lt;br&gt;
Now open Chrome and enter &lt;code&gt;chrome://inspect&lt;/code&gt; in the URL. DevTools page will appear. Notice the "Remote Target" section. Below it, you should be able to find the Fargate application for debugging.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html"&gt;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you like this post, please consider &lt;a href="https://www.buymeacoffee.com/amalj"&gt;buying me a coffee&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>node</category>
      <category>firstpost</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
