An example of how to create a Docker container application using Koa.js Next generation web framework for Node.js.
In the project root, initialize using Yarn or npm.
yarn init -y
Install dependencies.
yarn add koa
yarn add koa-body
yarn add koa-logger
yarn add koa-router
yarn add koa-views
yarn add swig
Create an app
folder in the project root.
In the app folder, create a folder named lib
. Then create this render.js
module in the new lib folder.
render.js
/**
* Module dependencies.
*/
const views = require('koa-views');
const path = require('path');
// setup views mapping .html
// to the swig template engine
module.exports = views(path.join(__dirname, '/../views'), {
map: { html: 'swig' }
});
In the app folder, create a folder for templates named views
. Then create this index.html
template in the new views folder.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>{{content}}</h1>
</body>
</html>
Using Emmet, which is built into VS Code, you can create the index.html content by entering an exclamation mark on the first line then select the tab key.
In the app folder, create this app.js
application entrypoint file.
app.js
const render = require('./lib/render');
const logger = require('koa-logger');
const router = require('koa-router')();
const koaBody = require('koa-body');
const Koa = require('koa');
const app = module.exports = new Koa();
// middleware
app.use(logger());
app.use(render);
app.use(koaBody());
// route definitions
router.get('/', index);
app.use(router.routes());
async function index(ctx) {
await ctx.render('index', { content: 'Hello World' });
}
// listen
if (!module.parent) app.listen(3000);
Project structure
project
┣ app
┃ ┣ lib
┃ ┃ ┗ render.js
┃ ┣ views
┃ ┃ ┗ index.html
┃ ┗ app.js
┗ package.json
Test the application locally in a browser at http://localhost:3000. Use Ctrl+C to kill the app after verifying it works.
cd app
node app.js
Docker
To containerize the application, create a docker-compose.yml
file in the project root as follows.
docker-compose.yml
version: '3'
services:
app:
image: node:alpine
user: "node"
working_dir: /home/node/app
environment:
- NODE_ENV=production
ports:
- "3000:3000"
volumes:
- ./app:/home/node/app
- ./node_modules:/home/node/node_modules
expose:
- "3000"
command: "node app.js"
Build, (re)create and start, the container in disconnected mode. The app
folder is attached as a volume and mapped to the working directory, /home/node/app
in the container. The node app.js
command is executed in the containers working directory.
docker-compose up -d
Test the application locally in a browser at http://localhost:3000. Use Ctrl+C to kill the app after verifying it works.
Stop and remove the container and volumes created by docker-compose up
.
docker-compose down
Build a Docker image for better performance and deployment once initial development is completed. Instead of mapping the local app
and node_modules
folders to the container, copy files and folders into the container, set working directories and run commands as needed.
Create this Dockerfile in the project root
Dockerfile
FROM node:alpine
WORKDIR /home/node
# using wildcard (*) to copy both package.json and package-lock.json
COPY package*.json /home/node/
RUN yarn install --production
# create and set app directory as current dir
WORKDIR /home/node/app
COPY app/ /home/node/app/
EXPOSE 3000
CMD ["node", "app.js"]
Build the image and tag it. In the project root run the following command.
docker build -t myapp-node .
Test the new myapp-node
Docker image using docker run
. Same URL as before, http://localhost:3000.
docker run -u node -w /home/node/app -e NODE_ENV=production -p 3000:3000 --expose 3000 myapp-node node "app.js"
Stop the container using docker stop
followed by the container ID. To get a list of all running containers, use docker ps --filter status=running
.
That's it!
This post originally published at jimfrenette.com/docker/node-js-koa-container
Top comments (0)