{"id":1460,"date":"2024-05-15T19:30:09","date_gmt":"2024-05-15T14:00:09","guid":{"rendered":"https:\/\/www.openwriteup.com\/?page_id=1460"},"modified":"2024-05-15T19:58:03","modified_gmt":"2024-05-15T14:28:03","slug":"windows-containers-two-tier-application-using-nodejs-and-postgres","status":"publish","type":"page","link":"https:\/\/www.openwriteup.com\/?page_id=1460","title":{"rendered":"Windows containers [Two tier application]: Using Nodejs and Postgres"},"content":{"rendered":"<p>This is one of the project, i did it for my client. In this blog i am using sample code from github.<\/p>\n<p><strong>Note: No Code has used from vendor ends, only sharing manifests files<\/strong><\/p>\n<ol>\n<li><span style=\"color: #000000;\"><span style=\"color: #0000ff;\"><span style=\"color: #000000;\">Open Powershell, Create a node app<\/span><\/span><\/span><\/li>\n<\/ol>\n<pre>mkdir docker-template\r\ncd docker-template\r\n# setup npm, download the package on windows\r\nhttps:\/\/nodejs.org\/dist\/v18.20.2\/node-v18.20.2-win-x64.zip\r\n#Extract the zip\r\n.\\npm init\r\n.\\npm install express<\/pre>\n<p>2. Create a Server.js file (using notepad command)<\/p>\n<pre>const express = require(\"express\");\r\nconst app = express();\r\nconst port = 8080;\r\napp.get(\"\/\", async (req, res) =&gt; {\r\nres.setHeader(\"Content-Type\", \"text\/html\");\r\nres.status(200);\r\nres.send(\"&lt;h1&gt;Hello world&lt;\/h1&gt;\");\r\n});\r\napp.listen(port, () =&gt; {\r\nconsole.log(`Example app listening at http:\/\/localhost:${port}`);<\/pre>\n<p>3. #Run the following command<\/p>\n<pre>\r\n.\\node.exe server.js<\/pre>\n<p>4. Open in Browser<\/p>\n<pre>http:\/\/localhost:8080<\/pre>\n<p>5. Let\u2019s containerize<\/p>\n<pre>\r\n1)Identify the windows OS\r\n2)Download the nodejs module\r\n3)Copy the required file\r\n4)Expose the port where it will listen\r\n5)Pass the command when it starts<\/pre>\n<p>6. Write Dockerfile<\/p>\n<pre>FROM mcr.microsoft.com\/windows\/servercore:1803 as installer\r\nSHELL [\"powershell\", \"-Command\", \"$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';\"]\r\nRUN Invoke-WebRequest -OutFile nodejs.zip -UseBasicParsing \"https:\/\/nodejs.org\/dist\/v18.20.2\/node-v18.20.2-win-x64.zip\";expand-archive nodejs.zip\r\nFROM mcr.microsoft.com\/windows\/nanoserver:1803\r\nWORKDIR \"C:\\nodejs\\node-v18.20.2-win-x64\"\r\nCOPY --from=installer \"C:\\nodejs\\node-v18.20.2-win-x64\" .\r\nRUN SETX PATH \"C:\\nodejs\\node-v18.20.2-win-x64\"\r\nRUN npm config set registry https:\/\/registry.npmjs.org\/\r\n# Create app directory\r\n# this is the location where you will be inside the container\r\nWORKDIR \/usr\/src\/app\r\n# Install app dependencies\r\n# A wildcard is used to ensure both package.json AND package-lock.json are copied\r\n# where available (npm@5+)\r\n# copying packages first helps take advantage of docker layers\r\nCOPY package*.json .\/\r\nRUN npm install\r\nCOPY . .\r\n# Make this port accessible from outside the container\r\n# Necessary for your browser to send HTTP requests to your Node app\r\nEXPOSE 8080\r\n# Command to run when the container is ready\r\n# Separate arguments as separate values in the array\r\nCMD [\"node\", \"server.js\"]<\/pre>\n<p>7.Build image<\/p>\n<pre>\r\nRename-Item .\\Dockerfile.txt .\\Dockerfile\r\ndocker build -t myapp .<\/pre>\n<p>8.\u00a0 Run the container<\/p>\n<pre>docker run -d --name=mynode -p 8080:8080 myapp\r\ndocker ps\r\n#open in browser http:\/\/localhost:8080<\/pre>\n<p>9. Identify the Image<\/p>\n<p>Setup postgres same way we setup nodejs<br \/>\nRef docker file:\u00a0 <span style=\"color: #0000ff;\"><a style=\"color: #0000ff;\" href=\"https:\/\/github.com\/stellirin\/docker-postgres-windows\/blob\/master\/Dockerfile\">Postgres dockerfile<\/a><\/span><br \/>\nCreate a table:database-seed.sql<\/p>\n<pre>CREATE TABLE employees\r\n(\r\nid SERIAL,\r\nname text,\r\ntitle text,\r\nCONSTRAINT employees_pkey PRIMARY KEY (id)\r\n);\r\nINSERT INTO employees(name, title) VALUES\r\n('Meadow Crystalfreak ', 'Head of Operations'),\r\n('Buddy-Ray Perceptor', 'DevRel'),\r\n('Prince Flitterbell', 'Marketing Guru');\r\n\r\n<\/pre>\n<p>10.Docker file for db:dbdockerfile<\/p>\n<pre>FROM stellirin\/postgres-windows\r\nWORKDIR docker-entrypoint-initdb.d\r\nCOPY \"database-seed.sql\" .\/<\/pre>\n<p>11. Run the dockerbuild command<\/p>\n<pre>\r\ndocker build -t dbpostgres -f .\\dbdockerfile .<\/pre>\n<p>12. Modify the server.js file<\/p>\n<pre>const { Client } = require(\"pg\");\r\nconst express = require(\"express\");\r\nconst app = express();\r\nconst port = 8080;\r\nconst dbConfig = {\r\npassword: \"root\",\r\nuser: \"root\",\r\nhost: \"postgres\",\r\n};\r\napp.use(express.static(\"public\"));\r\napp.get(\"\/employees\", async (req, res) =&gt; {\r\ntry {\r\nconst client = new Client(dbConfig); \/\/ Create a new client for each connection\r\nawait client.connect();\r\nconst results = await client.query(\"SELECT * FROM employees\");\r\nres.setHeader(\"Content-Type\", \"application\/json\");\r\nres.status(200);\r\nres.send(JSON.stringify(results.rows));\r\n} catch (error) {\r\nconsole.error(\"Query failed:\", error);\r\nres.status(500).send(\"Query failed\");\r\n}\r\n});\r\n(async () =&gt; {\r\napp.listen(port, () =&gt; {\r\nconsole.log(`Example app listening at http:\/\/localhost:${port}`);\r\n});\r\n})();<\/pre>\n<p>13. Create frontend files for the app<\/p>\n<pre>mkdir public\r\ncd public\r\nnotepad<\/pre>\n<p>14. Copy the below content, and save as index.html<\/p>\n<pre>&lt;!DOCTYPE html&gt;\r\n&lt;html lang=\"en\"&gt; &lt;head&gt; &lt;meta charset=\"UTF-8\" \/&gt; &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/&gt; &lt;title&gt;My Docker Template&lt;\/title&gt; &lt;script src=\"script.js\"&gt;&lt;\/script&gt; &lt;link rel=\"stylesheet\" href=\"styles.css\" \/&gt; &lt;\/head&gt; &lt;body&gt; &lt;template&gt; &lt;div class=\"card\"&gt; &lt;img src=\"https:\/\/res.cloudinary.com\/dqse2txyi\/image\/upload\/v1639943067\/blogs\/docker-node\/profile-picture_eav2ff.png\" alt=\"Avatar\" width=\"240px\" \/&gt; &lt;div class=\"container\"&gt; &lt;h4&gt;Placeholder&lt;\/h4&gt; &lt;p&gt;Placeholder&lt;\/p&gt; &lt;\/div&gt; &lt;\/div&gt; &lt;\/template&gt; &lt;\/body&gt; &lt;\/html&gt;<\/pre>\n<p>15.public\/styles.css<\/p>\n<pre>body {\r\npadding: 12px;\r\ndisplay: flex;\r\nflex-direction: row;\r\ncolumn-gap: 24px;\r\n}\r\n.card {\r\nbox-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);\r\ntransition: 0.3s;\r\nborder-radius: 5px;\r\ntransition: 0.3s;\r\n}\r\n.card:hover {\r\ntransform: scale(1.03);\r\n}\r\n.container {\r\npadding: 0 12px;\r\n}\r\nimg {\r\nborder-radius: 5px 5px 0 0;\r\n}<\/pre>\n<p>public\/script<\/p>\n<pre>fetch(\"\/employees\")\r\n.then((response) =&gt; response.json())\r\n.then((data) =&gt; {\r\ndata.forEach((employee) =&gt; {\r\n\/\/ Select the &lt;template&gt; we created in index.html\r\nconst cardTemplate = document.querySelector('template');\r\n\/\/ Clone a copy of the template we can insert in the DOM as a real visible node\r\nconst card = cardTemplate.content.cloneNode(true);\r\n\/\/ Update the content of the cloned template with the employee data we queried from the backend\r\ncard.querySelector('h4').innerText = employee.name;\r\ncard.querySelector('p').innerText = employee.title;\r\n\/\/ Append the card as a child with the employee data to the &lt;body&gt; element on our page\r\ndocument.body.appendChild(card);\r\n});\r\n});<\/pre>\n<pre>#Come out from public folder\r\ncd ..<\/pre>\n<p>16.Now build the app again<br \/>\nDocker file changes<\/p>\n<pre>FROM mcr.microsoft.com\/windows\/servercore:1803 as installer\r\nSHELL [\"powershell\", \"-Command\", \"$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';\"]\r\nRUN Invoke-WebRequest -OutFile nodejs.zip -UseBasicParsing \"https:\/\/nodejs.org\/dist\/v18.20.2\/node-v18.20.2-win-x64.zip\";expand-archive nodejs.zip\r\nFROM mcr.microsoft.com\/windows\/nanoserver:1803\r\nWORKDIR \"C:\\nodejs\\node-v18.20.2-win-x64\"\r\nCOPY --from=installer \"C:\\nodejs\\node-v18.20.2-win-x64\" .\r\n#RUN icacls . \/grant Everyone:(OI)(CI)F \/T\r\nRUN SETX PATH \"C:\\nodejs\\node-v18.20.2-win-x64\"\r\nRUN npm config set registry https:\/\/registry.npmjs.org\/\r\n# Create app directory\r\n# this is the location where you will be inside the container\r\nWORKDIR \/usr\/src\/app\r\n# Install app dependencies\r\n# A wildcard is used to ensure both package.json AND package-lock.json are copied\r\n# where available (npm@5+)\r\n# copying packages first helps take advantage of docker layers\r\nCOPY package*.json .\/\r\nRUN npm install\r\nRUN npm install pg\r\n# If you are building your code for production\r\n# RUN npm ci --only=production\r\nCOPY . .\r\n# Make this port accessible from outside the container\r\n# Necessary for your browser to send HTTP requests to your Node app\r\nEXPOSE 8080\r\n#CMD cmd.exe\r\n# Command to run when the container is ready\r\nCMD [\"node\", \"server.js\"]<\/pre>\n<p>17,<\/p>\n<pre>docker build -t mynode .\r\ndocker run -d --name=myapp -p 8080:8080 mynode\r\nStart the container for db first\r\ndocker run -d --name=postgres -e POSTGRES_USER=root -e POSTGRES_PASSWORD=root -e POSTGRES_DB=root -p 5432:5432 dbpostgres<\/pre>\n<p>18. Open in browser: http:\/\/localhost:8080<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is one of the project, i did it for my client. In this blog i am using sample code from github. Note: No Code has used from vendor ends, only sharing manifests files Open Powershell, Create a node app mkdir docker-template cd docker-template # setup npm, download the package on windows https:\/\/nodejs.org\/dist\/v18.20.2\/node-v18.20.2-win-x64.zip #Extract the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_oct_exclude_from_cache":false,"footnotes":""},"class_list":["post-1460","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=\/wp\/v2\/pages\/1460","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1460"}],"version-history":[{"count":4,"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=\/wp\/v2\/pages\/1460\/revisions"}],"predecessor-version":[{"id":1468,"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=\/wp\/v2\/pages\/1460\/revisions\/1468"}],"wp:attachment":[{"href":"https:\/\/www.openwriteup.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1460"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}