├── Dockerfile.onbuild ├── docker-compose.prod.yml ├── Dockerfile ├── docker-compose-onbuild.yml ├── docker-compose.yml ├── package.json ├── .vscode └── launch.json ├── nodemongoapp.dab ├── index.js ├── nginx.conf ├── README.md ├── .gitignore └── .dockerignore /Dockerfile.onbuild: -------------------------------------------------------------------------------- 1 | FROM node:onbuild 2 | 3 | -------------------------------------------------------------------------------- /docker-compose.prod.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | services: 4 | web: 5 | image: bretfisher/nodemongoapp 6 | environment: 7 | - MONGO_HOST=mongo 8 | mongo: 9 | image: mongo:latest 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | 3 | COPY ./package.json /src/ 4 | 5 | WORKDIR /src 6 | 7 | RUN npm install 8 | 9 | EXPOSE 8080 10 | EXPOSE 5858 11 | 12 | COPY . /src 13 | 14 | CMD ["npm", "start"] 15 | -------------------------------------------------------------------------------- /docker-compose-onbuild.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | web: 5 | image: node:onbuild 6 | ports: 7 | - "8080:8080" 8 | environment: 9 | - MONGO_HOST=mongo 10 | - .:/src 11 | mongo: 12 | image: mongo:latest 13 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | services: 4 | web: 5 | build: . 6 | command: nodemon --debug=5858 7 | ports: 8 | - "8080:8080" 9 | - "5858:5858" 10 | environment: 11 | - MONGO_HOST=mongo 12 | volumes: 13 | - .:/src 14 | mongo: 15 | image: mongo:latest 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docker-node-hello", 3 | "private": true, 4 | "version": "0.0.1", 5 | "description": "Node.js Hello world app using docker", 6 | "author": "Bret Fisher ", 7 | "dependencies": { 8 | "express": "^4.21.2", 9 | "mongodb": "^3.5.7" 10 | }, 11 | "scripts": { 12 | "start": "node index.js" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Attach", 6 | "type": "node", 7 | "request": "attach", 8 | "port": 5858, 9 | "address": "localhost", 10 | "restart": true, 11 | "sourceMaps": false, 12 | "outDir": null, 13 | "localRoot": "${workspaceRoot}", 14 | "remoteRoot": "/code" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /nodemongoapp.dab: -------------------------------------------------------------------------------- 1 | { 2 | "Services": { 3 | "mongo": { 4 | "Image": "mongo@sha256:e599c71179c2bbe0eab56a7809d4a8d42ddcb625b32a7a665dc35bf5d3b0f7c4", 5 | "Networks": [ 6 | "default" 7 | ] 8 | }, 9 | "web": { 10 | "Env": [ 11 | "MONGO_HOST=mongo" 12 | ], 13 | "Image": "bretfisher/nodemongoapp@sha256:eb03f85aaf2703e3866887bdef1de0670dd5135d8e861b8ab9cf7566b6786fb9", 14 | "Networks": [ 15 | "default" 16 | ], 17 | "Ports": [ 18 | { 19 | "Port": 8080, 20 | "Protocol": "tcp" 21 | } 22 | ] 23 | } 24 | }, 25 | "Version": "0.1" 26 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var mongodb = require('mongodb'); 3 | // Constants 4 | var PORT = 8080; 5 | 6 | // App 7 | var app = express(); 8 | app.get('/*', function (req, res) { 9 | // TODO: this doesn't return proper headers for nginx cache to HIT properly 10 | res.send('Hello world\n Check console for db connection info'); 11 | }); 12 | 13 | // Retrieve 14 | var MongoClient = require('mongodb').MongoClient; 15 | 16 | // Connect to the db 17 | MongoClient.connect("mongodb://mongo:27017/exampleDb", function(err, db) { 18 | if(!err) { 19 | console.log("We are connected"); 20 | } else { 21 | console.log("no connection to db OH NOS!!"); 22 | } 23 | }); 24 | 25 | app.listen(PORT); 26 | console.log('Running on http://localhost:' + PORT); 27 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | # setup proxy cache so we can use it in the below server 2 | proxy_cache_path /tmp/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m; 3 | proxy_cache_key "$scheme$request_method$host$request_uri"; 4 | 5 | server { 6 | 7 | listen 80; 8 | 9 | location / { 10 | 11 | proxy_pass http://web:8080; 12 | proxy_cache my_cache; 13 | proxy_cache_bypass $http_cache_control; 14 | add_header X-Proxy-Cache $upstream_cache_status; 15 | proxy_redirect off; 16 | proxy_set_header Host $host; 17 | proxy_set_header X-Real-IP $remote_addr; 18 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 19 | proxy_set_header X-Forwarded-Host $server_name; 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dockerized Example App: Node.js + Mongo 2 | 3 | A very simple example of a Node web app that connects to a mongo db. Each in its own 4 | container. I use this to illustrate many Docker concepts and techniques: 5 | 6 | - Use `Dockerfile` to build web app locally 7 | - Use `docker-compose.yml` to start web and mongo containers and mount source dir 8 | so you can dev locally, and show now multiple containers can work inside an overlay 9 | network. 10 | - User `docker-compose.prod.yml` to run `docker-compose bundle` for creating dab 11 | files to deploy in docker swarm. Scale web container and see how Routing Mesh works. 12 | 13 | 14 | ## Potential other lessions 15 | - Change to use `FROM node:onbuild` to show how a convenion-based node/npm app can 16 | get away with a single line Dockerfile for dev. 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/osx,node,vim 3 | 4 | ### OSX ### 5 | *.DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | .com.apple.timemachine.donotpresent 24 | 25 | # Directories potentially created on remote AFP share 26 | .AppleDB 27 | .AppleDesktop 28 | Network Trash Folder 29 | Temporary Items 30 | .apdisk 31 | 32 | 33 | ### Node ### 34 | # Logs 35 | logs 36 | *.log 37 | npm-debug.log* 38 | 39 | # Runtime data 40 | pids 41 | *.pid 42 | *.seed 43 | *.pid.lock 44 | 45 | # Directory for instrumented libs generated by jscoverage/JSCover 46 | lib-cov 47 | 48 | # Coverage directory used by tools like istanbul 49 | coverage 50 | 51 | # nyc test coverage 52 | .nyc_output 53 | 54 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 55 | .grunt 56 | 57 | # node-waf configuration 58 | .lock-wscript 59 | 60 | # Compiled binary addons (http://nodejs.org/api/addons.html) 61 | build/Release 62 | 63 | # Dependency directories 64 | node_modules 65 | jspm_packages 66 | 67 | # Optional npm cache directory 68 | .npm 69 | 70 | # Optional eslint cache 71 | .eslintcache 72 | 73 | # Optional REPL history 74 | .node_repl_history 75 | 76 | 77 | ### Vim ### 78 | # swap 79 | [._]*.s[a-w][a-z] 80 | [._]s[a-w][a-z] 81 | # session 82 | Session.vim 83 | # temporary 84 | .netrwhist 85 | *~ 86 | # auto-generated tag files 87 | tags 88 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | #docker 2 | .git 3 | 4 | # Created by https://www.gitignore.io/api/osx,node,vim 5 | 6 | ### OSX ### 7 | *.DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | 15 | # Thumbnails 16 | ._* 17 | 18 | # Files that might appear in the root of a volume 19 | .DocumentRevisions-V100 20 | .fseventsd 21 | .Spotlight-V100 22 | .TemporaryItems 23 | .Trashes 24 | .VolumeIcon.icns 25 | .com.apple.timemachine.donotpresent 26 | 27 | # Directories potentially created on remote AFP share 28 | .AppleDB 29 | .AppleDesktop 30 | Network Trash Folder 31 | Temporary Items 32 | .apdisk 33 | 34 | 35 | ### Node ### 36 | # Logs 37 | logs 38 | *.log 39 | npm-debug.log* 40 | 41 | # Runtime data 42 | pids 43 | *.pid 44 | *.seed 45 | *.pid.lock 46 | 47 | # Directory for instrumented libs generated by jscoverage/JSCover 48 | lib-cov 49 | 50 | # Coverage directory used by tools like istanbul 51 | coverage 52 | 53 | # nyc test coverage 54 | .nyc_output 55 | 56 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 57 | .grunt 58 | 59 | # node-waf configuration 60 | .lock-wscript 61 | 62 | # Compiled binary addons (http://nodejs.org/api/addons.html) 63 | build/Release 64 | 65 | # Dependency directories 66 | node_modules 67 | jspm_packages 68 | 69 | # Optional npm cache directory 70 | .npm 71 | 72 | # Optional eslint cache 73 | .eslintcache 74 | 75 | # Optional REPL history 76 | .node_repl_history 77 | 78 | 79 | ### Vim ### 80 | # swap 81 | [._]*.s[a-w][a-z] 82 | [._]s[a-w][a-z] 83 | # session 84 | Session.vim 85 | # temporary 86 | .netrwhist 87 | *~ 88 | # auto-generated tag files 89 | tags 90 | --------------------------------------------------------------------------------