<?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: Dong Nguyen</title>
    <description>The latest articles on DEV Community by Dong Nguyen (@ndaidong).</description>
    <link>https://dev.to/ndaidong</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%2F61429%2F8c2f20ed-c52f-4865-9053-5b1b344bdc6d.png</url>
      <title>DEV Community: Dong Nguyen</title>
      <link>https://dev.to/ndaidong</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ndaidong"/>
    <language>en</language>
    <item>
      <title>How to make your MongoDB container more secure?</title>
      <dc:creator>Dong Nguyen</dc:creator>
      <pubDate>Sun, 13 Sep 2020 13:59:56 +0000</pubDate>
      <link>https://dev.to/ndaidong/how-to-make-your-mongodb-container-more-secure-1646</link>
      <guid>https://dev.to/ndaidong/how-to-make-your-mongodb-container-more-secure-1646</guid>
      <description>&lt;h2&gt;
  
  
  Start it with docker
&lt;/h2&gt;

&lt;p&gt;The most simple way to get MongoDB instance in your machine is using docker to run &lt;a href="https://hub.docker.com/_/mongo" rel="noopener noreferrer"&gt;mongodb image&lt;/a&gt; on docker hub as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; mongodb &lt;span class="nt"&gt;-p&lt;/span&gt; 27017:27017 mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By specifying &lt;code&gt;-p 27017:27017&lt;/code&gt;, you can access to it with the connection string such as &lt;code&gt;mongodb://localhost:27017&lt;/code&gt; or &lt;code&gt;mongodb://0.0.0.0:27017&lt;/code&gt;, as same as installed MongoDB server.&lt;/p&gt;

&lt;p&gt;This database instance is only available locally. In the case you want to access to it from another computer, you have to overwrite the default config file with a custom MongoDB configuration file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Allow to connect from outside
&lt;/h2&gt;

&lt;p&gt;The command looks like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; mongodb &lt;span class="nt"&gt;-p&lt;/span&gt; 27017:27017 &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/custom/mongod.conf:/etc/mongod.conf mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In which, the &lt;code&gt;mongod.conf&lt;/code&gt; file has been customized to allow to connect from outside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# mongod.conf
&lt;/span&gt;
&lt;span class="c"&gt;# other settings
&lt;/span&gt;
&lt;span class="c"&gt;# network interfaces
&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;:
  &lt;span class="n"&gt;port&lt;/span&gt;: &lt;span class="m"&gt;27017&lt;/span&gt;
  &lt;span class="c"&gt;# bindIp: 127.0.0.1  # this is default setting
&lt;/span&gt;  &lt;span class="n"&gt;bindIp&lt;/span&gt;: &lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;  &lt;span class="c"&gt;# this is what changed
&lt;/span&gt;
&lt;span class="c"&gt;# other settings
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But since now your database is public and no longer secure.&lt;/p&gt;

&lt;p&gt;In my experience, the first thing we should do in this situation is change the default port. &lt;/p&gt;

&lt;h2&gt;
  
  
  Change default port
&lt;/h2&gt;

&lt;p&gt;Let's map it to another free port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; mongodb &lt;span class="nt"&gt;-p&lt;/span&gt; 27117:27017 &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/custom/mongod.conf:/etc/mongod.conf mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that the connection string will become &lt;code&gt;mongodb://IP_ADDRESS:27117&lt;/code&gt;, not default port.&lt;/p&gt;

&lt;p&gt;As you know, there are many bots those automatically scan for public databases on the internet. They try to check the popular default ports, such as 3306 (mysql), 5432 (posgres), 6379 (redis), 27017 (mongo), etc. Changing to a strange port may help you in almost cases.&lt;/p&gt;

&lt;p&gt;However, that's not enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable authentication
&lt;/h2&gt;

&lt;p&gt;By default MongoDB will start with authentication disabled. We should enable it with a little bit change to entrypoint. In order to make things easier management, we create a docker-compose.yaml file as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mongodb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongodb&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;27117:27017&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./mongod.conf:/etc/mongod.conf&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mongod"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--auth"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--config"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/etc/mongod.conf"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above .yaml file, we added our custom entrypoint to run mongodb with &lt;code&gt;--auth&lt;/code&gt; flag. Now when we run it with docker-compose, we should get MongoDB within a container named &lt;code&gt;mongodb&lt;/code&gt; similar to the &lt;code&gt;docker run&lt;/code&gt; command earlier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8ebsbyfwhdzr6dvdobd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8ebsbyfwhdzr6dvdobd.png" width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the following is the most important parts of this article...&lt;/p&gt;

&lt;h3&gt;
  
  
  Create users with specific permissions
&lt;/h3&gt;

&lt;p&gt;Until now, our MongoDB instance does not have any user yet. We will get into its container and create a few ones.&lt;/p&gt;

&lt;p&gt;Firstly, let's get the interactive mongo shell by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; mongodb mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With opening mongo shell, we can now run the commands to switch to &lt;code&gt;admin&lt;/code&gt; database and create a user named &lt;code&gt;boss&lt;/code&gt; with admin permission on any database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;use admin
db.createUser&lt;span class="o"&gt;({&lt;/span&gt;
  user: &lt;span class="s1"&gt;'boss'&lt;/span&gt;,
  &lt;span class="nb"&gt;pwd&lt;/span&gt;: &lt;span class="s1"&gt;'YourVeryComplexPassword'&lt;/span&gt;,
  roles:[&lt;span class="s1"&gt;'userAdminAnyDatabase'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done, press Ctrl + C to exit the shell and leave that session.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrg300wcrev9knryeloq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrg300wcrev9knryeloq.png" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that, at this time, we had already a MongoDB instance run with authentication mode enabled, and an admin user. The connection string for &lt;code&gt;boss&lt;/code&gt; user now looks like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mongodb://boss:YourVeryComplexPassword@IP_ADDR:27117&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But that's power user, don't use it for regular applications. Instead, we should create more users for different purposes.&lt;/p&gt;

&lt;p&gt;To create more user or database, we have to come back to mongo shell as &lt;code&gt;boss&lt;/code&gt; user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; mongodb mongo &lt;span class="nt"&gt;-u&lt;/span&gt; boss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter password when asked and you should see something like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h4t65ymq4eqn737rtpi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h4t65ymq4eqn737rtpi.png" width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assume that we have a plan to use a database &lt;code&gt;blogs&lt;/code&gt; to store our great blog posts. We should add a user named &lt;code&gt;writer&lt;/code&gt; which can write to this database, and a user named &lt;code&gt;reader&lt;/code&gt; which can read only.&lt;/p&gt;

&lt;p&gt;Do that as below:&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;# go to database `admin`&lt;/span&gt;
use admin

&lt;span class="c"&gt;# add writer&lt;/span&gt;
db.createUser&lt;span class="o"&gt;({&lt;/span&gt;
  user: &lt;span class="s1"&gt;'writer'&lt;/span&gt;,
  &lt;span class="nb"&gt;pwd&lt;/span&gt;: &lt;span class="s1"&gt;'YourComplexPassword'&lt;/span&gt;,
  roles:[
    &lt;span class="o"&gt;{&lt;/span&gt; 
      role: &lt;span class="s1"&gt;'readWrite'&lt;/span&gt;,
      db: &lt;span class="s1"&gt;'blogs'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;})&lt;/span&gt;

&lt;span class="c"&gt;# add reader&lt;/span&gt;
db.createUser&lt;span class="o"&gt;({&lt;/span&gt;
  user: &lt;span class="s1"&gt;'reader'&lt;/span&gt;,
  &lt;span class="nb"&gt;pwd&lt;/span&gt;: &lt;span class="s1"&gt;'YourSimplePassword'&lt;/span&gt;,
  roles:[
    &lt;span class="o"&gt;{&lt;/span&gt; 
      role: &lt;span class="s1"&gt;'read'&lt;/span&gt;,
      db: &lt;span class="s1"&gt;'blogs'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done, press Ctrl + C to exit the shell and leave that session again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswnvjtvwezmvzbfpav5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswnvjtvwezmvzbfpav5z.png" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have 2 new users, one for read/write and other for read only action. Their connection strings are:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mongodb://writer:YourComplexPassword@IP_ADDR:27117&lt;/code&gt;&lt;br&gt;
&lt;code&gt;mongodb://reader:YourSimplePassword@IP_ADDR:27117&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With the apps or API endpoints those only load and show blog posts, we just need to use the connection string for &lt;code&gt;reader&lt;/code&gt;. Otherwise, when we need to add more blog posts, we will connect to database as &lt;code&gt;writer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's it. Enjoy playing with docker and MongoDB :)&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>docker</category>
      <category>security</category>
    </item>
    <item>
      <title>6 things I just learned after implementing my first Deno web service</title>
      <dc:creator>Dong Nguyen</dc:creator>
      <pubDate>Sat, 22 Aug 2020 10:20:58 +0000</pubDate>
      <link>https://dev.to/ndaidong/6-things-i-just-learned-after-implementing-my-first-deno-web-service-18a8</link>
      <guid>https://dev.to/ndaidong/6-things-i-just-learned-after-implementing-my-first-deno-web-service-18a8</guid>
      <description>&lt;p&gt;As I've shared yesterday about &lt;a href="https://dev.to/ndaidong/would-you-like-to-play-with-microservices-1ahh"&gt;my list of microservices&lt;/a&gt;, today I try to implement an &lt;a href="https://github.com/ndaidong/microservices/tree/main/api-gateway-deno" rel="noopener noreferrer"&gt;API Gateway with Deno&lt;/a&gt;. Because I've created &lt;a href="https://github.com/ndaidong/microservices/tree/main/api-gateway-node" rel="noopener noreferrer"&gt;Node.js version&lt;/a&gt; early, I though that it should be very simple to migrate to Deno, but not really. It taken about 3 hours of  reading the documentation and some tutorials!&lt;/p&gt;

&lt;p&gt;Here are some notes for reference later.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Server and HTTPOptions
&lt;/h3&gt;

&lt;p&gt;Similar to Node.js, Deno provides &lt;a href="https://deno.land/std@0.66.0/http" rel="noopener noreferrer"&gt;http&lt;/a&gt;, a standard library to handle web server. I've played with it a little bit. Then I quickly found that there is a drop-in replacement for Express named &lt;a href="https://deno.land/x/opine@0.21.2" rel="noopener noreferrer"&gt;opine&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;So I switch to this lib. It works almost the same as Express, but incomplete, and the &lt;code&gt;listen&lt;/code&gt; method is quite different.&lt;/p&gt;

&lt;p&gt;With Express, to set &lt;code&gt;host&lt;/code&gt; and &lt;code&gt;port&lt;/code&gt;, we can just write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onServerReady&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But with Opine's &lt;code&gt;app&lt;/code&gt; instance, the following ways didn't work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onServerReady&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onServerReady&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;onServerReady&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no docs/examples relating to this issue, so I have to look in the &lt;a href="https://deno.land/x/opine@0.21.2/src/application.ts#L516" rel="noopener noreferrer"&gt;source code&lt;/a&gt; and see that they use &lt;code&gt;HTTPOptions&lt;/code&gt; and &lt;code&gt;HTTPSOptions&lt;/code&gt; from the standard &lt;a href="https://deno.land/std@0.65.0/http/server.ts#L314" rel="noopener noreferrer"&gt;http/server&lt;/a&gt; library. They didn't use the property name &lt;code&gt;host&lt;/code&gt; as &lt;a href="https://nodejs.org/api/net.html#net_server_listen_options_callback" rel="noopener noreferrer"&gt;server.listen() in Node.js&lt;/a&gt;, but &lt;code&gt;hostname&lt;/code&gt;. So, the correct way is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;onServerReady&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. HTTP Proxy
&lt;/h3&gt;

&lt;p&gt;As other API Gateway, I need to map some endpoints to the actual services behind the scene. In Node.js, I use &lt;a href="https://www.npmjs.com/package/http-proxy-middleware" rel="noopener noreferrer"&gt;http-proxy-middleware&lt;/a&gt;. In Deno, there is &lt;a href="https://deno.land/x/opineHttpProxy@2.1.0" rel="noopener noreferrer"&gt;opine-http-proxy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I haven't dig into these libs enough yet. But the basic method I'm using shows a little bit of a difference. &lt;/p&gt;

&lt;p&gt;With express/http-proxy-middleware, if we write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;createProxyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://abc.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, any request to &lt;code&gt;{API_GATEWAY_DOMAIN}/login&lt;/code&gt; will be forwarded to &lt;code&gt;https://abc.com/login&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;But, with opine/opine-http-proxy, we have to write exactly the path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;createProxyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://abc.com/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. The flags
&lt;/h3&gt;

&lt;p&gt;With Node.js, we simple run &lt;code&gt;node script.js&lt;/code&gt; and everything should work well. But with Deno, &lt;code&gt;deno run script.ts&lt;/code&gt; may not work as expected. Because, Deno does not grant any permission to running script by default. So, if the script needs to access to the network, it must be started with the flag &lt;code&gt;--allow-net&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deno run --allow-net script.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it also needs to load a file from hard disk, it must be started with the flag &lt;code&gt;--allow-read&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deno run --allow-net --allow-read script.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is also &lt;code&gt;--allow-write&lt;/code&gt; to write files, &lt;code&gt;--allow-env&lt;/code&gt; to get environment variables, &lt;code&gt;--allow-run&lt;/code&gt; to run sub processes, and &lt;a href="https://deno.land/manual/getting_started/command_line_interface" rel="noopener noreferrer"&gt;more here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However we can use &lt;code&gt;--allow-all&lt;/code&gt; to enable all the permission so it would work as same as Node.js, but we shouldn't - that is the unique value by Deno.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;code&gt;readJson&lt;/code&gt; and &lt;code&gt;--unstable&lt;/code&gt; flag
&lt;/h3&gt;

&lt;p&gt;Because in my service there is always &lt;a href="https://github.com/ndaidong/microservices#servicejson-file" rel="noopener noreferrer"&gt;a &lt;code&gt;service.json&lt;/code&gt; file&lt;/a&gt; to define service settings, I need to parse JSON file.&lt;/p&gt;

&lt;p&gt;Similar to Node.js, Deno provides a standard library called &lt;a href="https://deno.land/std@0.66.0/fs" rel="noopener noreferrer"&gt;fs&lt;/a&gt; too. And I found that there is few familiar methods to deal with JSON content there.&lt;/p&gt;

&lt;p&gt;However, the following does not work:&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="err"&gt;import&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="err"&gt;readJson&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="err"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://deno.land/std/fs/mod.ts"&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0xro7psx1p37fmyskam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0xro7psx1p37fmyskam.png" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you see, it loads many unnecessary modules and requires to add &lt;code&gt;--unstable&lt;/code&gt; to the command, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deno run &lt;span class="nt"&gt;--allow-net&lt;/span&gt; &lt;span class="nt"&gt;--allow-read&lt;/span&gt; &lt;span class="nt"&gt;--unstable&lt;/span&gt; app.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case you don't like the unstable things, you can refer their &lt;a href="https://deno.land/std@0.66.0/fs/read_json.ts" rel="noopener noreferrer"&gt;read_json.ts&lt;/a&gt; and write your own method, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;readJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readTextFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Built-in logger
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://deno.land/std@0.66.0/log" rel="noopener noreferrer"&gt;log&lt;/a&gt; library in Deno looks quite similar to Python &lt;a href="https://docs.python.org/3.8/library/logging.html" rel="noopener noreferrer"&gt;logging&lt;/a&gt; module. Because I also work with Python so this is not very hard to get familiar with.&lt;/p&gt;

&lt;p&gt;This lib supports file rotating, custom format and handlers. So we don't need to use any third party module as with  Node.js we must.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Which docker image for Deno should be chosen?
&lt;/h3&gt;

&lt;p&gt;While Deno team didn't build any official docker image yet, I recommend to use &lt;a href="https://hub.docker.com/r/hayd/deno" rel="noopener noreferrer"&gt;hayd/deno-docker&lt;/a&gt;. Because it is updated regularly and there is &lt;a href="https://github.com/denoland/deno/issues/3356" rel="noopener noreferrer"&gt;a discussion&lt;/a&gt; about making it official.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Node.js is cool. Deno is cool too. There is no &lt;code&gt;package.json&lt;/code&gt;, nor &lt;code&gt;node_modules&lt;/code&gt;. That makes things look more simple and clean. The standard libraries and built-in tools are great. But this ecosystem will need more time to mature...&lt;/p&gt;

</description>
      <category>deno</category>
      <category>microservices</category>
      <category>node</category>
    </item>
    <item>
      <title>Would you like to play with microservices?</title>
      <dc:creator>Dong Nguyen</dc:creator>
      <pubDate>Fri, 21 Aug 2020 14:34:51 +0000</pubDate>
      <link>https://dev.to/ndaidong/would-you-like-to-play-with-microservices-1ahh</link>
      <guid>https://dev.to/ndaidong/would-you-like-to-play-with-microservices-1ahh</guid>
      <description>&lt;p&gt;Hello guys,&lt;/p&gt;

&lt;p&gt;I just created a (quite long) list of services to implement, just for learning and practice more about microservices, node, deno, python, golang, vlang, and some new tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ndaidong/microservices" rel="noopener noreferrer"&gt;https://github.com/ndaidong/microservices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But studying alone is boring! If you have the same plan to learn the same things with me, feel free to fork and contribute. Together, we can build a set of useful sample source codes for reference.&lt;/p&gt;

&lt;p&gt;Or, if you have any other opinion, please share to me :)&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>python</category>
      <category>go</category>
      <category>node</category>
    </item>
    <item>
      <title>7 habits for better git usage</title>
      <dc:creator>Dong Nguyen</dc:creator>
      <pubDate>Mon, 08 Jun 2020 15:16:10 +0000</pubDate>
      <link>https://dev.to/ndaidong/7-habits-for-better-git-usage-2fo3</link>
      <guid>https://dev.to/ndaidong/7-habits-for-better-git-usage-2fo3</guid>
      <description>&lt;ul&gt;
&lt;li&gt;everything begins with an issue&lt;/li&gt;
&lt;li&gt;always check the current branch before making any changes&lt;/li&gt;
&lt;li&gt;run "git pull" as often as possible&lt;/li&gt;
&lt;li&gt;commit as soon as possible&lt;/li&gt;
&lt;li&gt;commit should be referenced to the related issues&lt;/li&gt;
&lt;li&gt;never push changes to the main branch directly&lt;/li&gt;
&lt;li&gt;always keep the tree tidy by cleaning old branches&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>productivity</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
