{"id":3533,"date":"2025-12-30T19:07:20","date_gmt":"2025-12-30T10:07:20","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=3533"},"modified":"2026-01-02T20:35:46","modified_gmt":"2026-01-02T11:35:46","slug":"linuxdockerpostgresqldockerexpresspostgresql","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2025\/12\/30\/linuxdockerpostgresqldockerexpresspostgresql\/","title":{"rendered":"[linux,docker,postgresql]docker+express+postgresql"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \uc544\ub798\ub294 \ub3c4\ucee4+express+postgresql\ub370\uc774\ud130 \ubca0\uc774\uc2a4\ub97c \uc5f0\ub3d9\ud558\ub294 \uc608\uc81c \ucf54\ub4dc \uc785\ub2c8\ub2e4. <br>Below is an example code that connects Docker + Express + PostgreSQL database.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \ub514\ub809\ud1a0\ub9ac \/ directory<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>my-app\/\n\u251c\u2500\u2500 Dockerfile          \n\u251c\u2500\u2500 compose.yaml  \n\u251c\u2500\u2500 package.json\n\u251c\u2500\u2500 app.js           \n\u251c\u2500\u2500 .env\n\u251c\u2500\u2500 db.js\n\u251c\u2500\u2500 routes\/index.js\n\u251c\u2500\u2500 routes\/health.js\n\u2514\u2500\u2500 ... <\/code><\/pre>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb Dockerfile<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FROM node:24-alpine\n\nWORKDIR \/app\n\nCOPY package*.json .\/\nRUN npm install  \nCOPY . .\n\nEXPOSE 3000\nCMD &#91;\"node\", \"app.js\"]<\/code><\/pre>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \ucf54\ub4dc \/ code<\/p>\n\n\n\n<p>\u2714\ufe0f compose.yaml<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>services:\n  db:\n    image: mysql:8.0\n    restart: always\n    environment:\n      MYSQL_ROOT_PASSWORD: Myapp@1234\n      MYSQL_DATABASE: myapp\n      MYSQL_USER: myapp\n      MYSQL_PASSWORD: Myapp@1234\n    volumes:\n      - .\/mysql-data:\/var\/lib\/mysql\n    ports:\n      - \"3306:3306\"\n\n  app:\n    build: .\n    restart: always\n    depends_on:\n      - db\n    environment:\n      DB_HOST: db\n      DB_USER: myapp\n      DB_PASSWORD: Myapp@1234\n      DB_NAME: myapp\n      DB_PORT: 3306\n    ports:\n      - \"3000:3000\"\n    volumes:\n      - .:\/app                  # \uac1c\ubc1c \uc911 \ucf54\ub4dc \ubcc0\uacbd \uc989\uc2dc \ubc18\uc601\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app.js<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>require(\"dotenv\").config();\nconst express = require(\"express\");\nconst app = express();\nconst port = 3000;\n\napp.use(express.json());\n\nconst indexRouter = require(\".\/routes\/index\");\napp.use(\"\/\", indexRouter);\napp.use(\"\/health\", require(\".\/routes\/health\"));\n\napp.listen(port, () =&gt; {\n  console.log(`Express server running on port ${port}`);\n});\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f .env<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>POSTGRES_USER=myapp\nPOSTGRES_PASSWORD=myapp@1234\nPOSTGRES_DB=myapp<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f db.js<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const { Pool } = require(\"pg\");\n\nconst pool = new Pool({\n  host: process.env.DB_HOST || \"localhost\",\n  port: process.env.DB_PORT || 5432,\n  user: process.env.POSTGRES_USER,\n  password: process.env.POSTGRES_PASSWORD,  \n  database: process.env.POSTGRES_DB,\n  \n  \/\/ \uc5f0\uacb0 \ud480 \uc124\uc815 (\uc120\ud0dd)\n  \/\/ Set up connection pool (optional)\n  max: 10,\n  idleTimeoutMillis: 30000,\n});\n\n\/\/ \uc5f0\uacb0 \uc624\ub958 \uc2dc \ub85c\uadf8 \ub0a8\uae30\uae30 (\ub514\ubc84\uae45\uc6a9)\n\/\/ Leave a log when a connection error occurs (for debugging)\npool.on(\"error\", (err) => {\n  console.error(\"Unexpected error on idle client\", err.stack);\n});\n\nmodule.exports = pool;<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f routes\/index.js<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const express = require(\"express\");\nconst router = express.Router();\nconst pool = require(\"..\/db\");\n\n\/\/ GET \/\nrouter.get(\"\/\", async (req, res) => {\n  try {\n    \/\/ PostgreSQL \ud604\uc7ac \uc2dc\uac04 \uc870\ud68c\n    \/\/ PostgreSQL current time query\n    const result = await pool.query(\"SELECT CURRENT_TIMESTAMP AS now\");\n\n    res.json({\n      success: true,\n      message: \"Connected to PostgreSQL successfully!\",\n      serverTime: result.rows&#91;0].now,\n    });\n  } catch (err) {\n    console.error(\"Database query error:\", err.stack);\n    res.status(500).json({\n      success: false,\n      error: \"Database connection failed\",\n    });\n  }\n});\n\nmodule.exports = router;\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f routes\/health.js<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const express = require(\"express\");\nconst router = express.Router();\nconst pool = require(\"..\/db\"); \n\n\/\/ GET \/health\nrouter.get(\"\/\", async (req, res) => {\n  try {\n    \/\/ PostgreSQL \uc5f0\uacb0 \ud14c\uc2a4\ud2b8: \uac04\ub2e8\ud55c \ucffc\ub9ac\ub85c \uc5f0\uacb0 \uc0c1\ud0dc \ud655\uc778\n    \/\/ Test PostgreSQL connection: Check connection status with a simple query\n    await pool.query(\"SELECT 1\");\n\n    \/\/ DB \uc5f0\uacb0\uc774 \uc815\uc0c1\uc77c \ub54c\n    \/\/ When the DB connection is normal\n    res.json({\n      status: \"UP\",\n      message: \"Service is healthy\",\n      timestamp: new Date().toISOString(),\n    });\n  } catch (err) {\n    \/\/ DB \uc5f0\uacb0 \uc2e4\ud328 \ub610\ub294 \ucffc\ub9ac \uc5d0\ub7ec \ubc1c\uc0dd \uc2dc\n    \/\/ When DB connection fails or query error occurs\n    console.error(\"Health check failed:\", err.message);\n\n    res.status(503).json({\n      status: \"DOWN\",\n      message: \"Database connection failed\",\n      timestamp: new Date().toISOString(),\n      \/\/ \uac1c\ubc1c \ud658\uacbd\uc5d0\uc11c\ub9cc \uc0c1\uc138 \uc5d0\ub7ec \ub178\ucd9c \n      \/\/ Detailed errors are only displayed in the development environment.\n      \/\/ error: process.env.NODE_ENV === \"development\" ? err.message : undefined,\n    });\n  }\n});\n\nmodule.exports = router;<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f package.json<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"name\": \"postgresqlmyapp\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"license\": \"ISC\",\n  \"author\": \"\",\n  \"type\": \"commonjs\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" &amp;&amp; exit 1\"\n  },\n  \"dependencies\": {\n    \"dotenv\": \"^17.2.3\",\n    \"express\": \"^5.2.1\",\n    \"pg\": \"^8.16.3\"\n  }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \uc544\ub798\ub294 \ub3c4\ucee4+express+postgresql\ub370\uc774\ud130 \ubca0\uc774\uc2a4\ub97c \uc5f0\ub3d9\ud558\ub294 \uc608\uc81c \ucf54\ub4dc \uc785\ub2c8\ub2e4. Below is an example code that connects Docker + Express + PostgreSQL database. \ud83d\udc49\ud83c\udffb \ub514\ub809\ud1a0\ub9ac \/ directory \ud83d\udc49\ud83c\udffb Dockerfile \ud83d\udc49\ud83c\udffb \ucf54\ub4dc \/ code \u2714\ufe0f compose.yaml \u2714\ufe0f app.js \u2714\ufe0f .env \u2714\ufe0f db.js \u2714\ufe0f routes\/index.js \u2714\ufe0f routes\/health.js \u2714\ufe0f package.json<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,1],"tags":[],"class_list":["post-3533","post","type-post","status-publish","format-standard","hentry","category-linux","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/3533","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=3533"}],"version-history":[{"count":21,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/3533\/revisions"}],"predecessor-version":[{"id":3667,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/3533\/revisions\/3667"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=3533"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=3533"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=3533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}