Docker for Development
Docker for Development
  • ✅ Setup the Dev env

  • ✅ Setup the Tests env

  • ✅ Deploy to Prod env

  • ✅ Pray

👨🏻‍💻

the Dev env

GITHUB/ANYHUB
Branch
Master

👨🏻‍💻

👨🏻‍💻

Example

Let's create simple ⚛️ React App

            
demo@demo:$ npx create-react-app react_demo && yarn start
           
            Compiled successfully!
  You can now view react_demo in the browser.

    Local:            http://localhost:3000
    On Your Network:  http://192.168.0.88:3000

  Note that the development build is not optimized.
  To create a production build, use yarn build.
          
            
demo@demo:$ cd react_demo && tree
           
           ➞ tree
           .
           ├── README.md
           ├── package.json
           ├── public
           │   ├── favicon.ico
           │   ├── index.html
           │   ├── logo192.png
           │   ├── logo512.png
           │   ├── manifest.json
           │   └── robots.txt
           ├── src
           │   ├── App.css
           │   ├── App.js
           │   ├── App.test.js
           │   ├── index.css
           │   ├── index.js
           │   ├── logo.svg
           │   ├── serviceWorker.js
           │   └── setupTests.js
           └── yarn.lock
           
           2 directories, 17 files
          
             
            ➞ tree
            .
            ├── README.md
            ├── package.json
            ├── Dockerfile.dev
            ├── public
            │   ├── favicon.ico
            │   ├── index.html
            │   ├── logo192.png
            │   ├── logo512.png
            │   ├── manifest.json
            │   └── robots.txt
            ├── src
            │   ├── App.css
            │   ├── App.js
            │   ├── App.test.js
            │   ├── index.css
            │   ├── index.js
            │   ├── logo.svg
            │   ├── serviceWorker.js
            │   └── setupTests.js
            └── yarn.lock
            
            2 directories, 17 files
            
           
             
                FROM node:latest
                RUN mkdir -p /usr/src/app
                WORKDIR /usr/src/app
                COPY package.json .
                RUN yarn install
                COPY . .
                CMD ["yarn" ,"start" ]
            
           
            
 d build -t react_app -f dockerfile.dev . && d run -it  -p 3000:3000 react_app
            
           

      Compiled successfully!

      You can now view react_demo in the browser.
      
        Local:            http://localhost:3000
        On Your Network:  http://172.17.0.2:3000
      
      Note that the development build is not optimized.
      To create a production build, use yarn build.

           
             
      FROM node:latest
      RUN mkdir -p /usr/src/app
      WORKDIR /usr/src/app
      COPY package.json .
      RUN yarn install
      COPY . .
      CMD ["yarn" ,"start" ]
            
           

🤔

rebuild

volumes

fs mapping

            
 d run -it  -p 3000:3000 -v $(pwd):/usr/src/app react_app
            
           
            
        ➞ d run -it  -p 3000:3000 -v $(pwd):/usr/src/app react_app

        yarn run v1.22.5
        $ react-scripts start
        /bin/sh: 1: react-scripts: not found
        error Command failed with exit code 127.
        
           
             
      FROM node:latest
      RUN mkdir -p /usr/src/app
      WORKDIR /usr/src/app
      COPY package.json .
      RUN yarn install
      COPY . .
      CMD ["yarn" ,"start" ]
            
           
            
 d run -it  -p 3000:3000 -v $(pwd):/usr/src/app react_app
            
           

  ➞ d run -it  -p 3000:3000 -v $(pwd):/usr/src/app -v /usr/src/app/node_modules react_app
          

  ➞ d run -it  -p 3000:3000 -v $(pwd):/usr/src/app react_app
            
            Compiled successfully!

            You can now view react_demo in the browser.
            
              Local:            http://localhost:3000
              On Your Network:  http://172.17.0.2:3000
            
            Note that the development build is not optimized.
            To create a production build, use yarn build.
        
           

🧐

Full Stack

CLIENT
BACKEND
DB
REST-API
GQL
LOG
BATCH
BACKUP
PROXY

🤓

What If ?

docker compose

CLIENT
BACKEND
DB
REST-API
GQL
LOG
BATCH
BACKUP
PROXY
CLIENT
BACKEND

Folder structure

            
 ➞ tree -d .
.
├── mongo
│   └── ...
├── nmap
│   └── ...
├── praser
│   └── ...
├── reactApp (client)
│   └── ...
├── backend 
    └── ...
  
            

⚛️ React App


  ➞ d run -it  -p 3000:3000 -v $(pwd):/usr/src/app -v /usr/src/app/node_modules react_app

     
    FROM node:latest
    RUN mkdir -p /usr/src/app
    WORKDIR /usr/src/app
    COPY package.json .
    RUN yarn install
    COPY . .
    CMD ["yarn" ,"start" ]
    
          
docker-compose.yml
     
      version: '3'
      volumes:
        mongoVolume:
        sharedFolder:
      
      services:
        mongo-server:
          image: 'mongo'
          restart: always
          volumes:
            - mongoVolume:/data/db
          ports:
            - 27017:27017
        nmap:
          build: nmap/.
          restart: always
          volumes:
            - sharedFolder:/usr/src/app/data
        parser:
          build: parser/.
          restart: always
          volumes:
            - sharedFolder:/usr/src/app/data
          environment:
            - MONGO_HOST=mongo-server
    
          
     
      version: '3'
      volumes:
        mongoVolume:
        sharedFolder:
      
      services:
        mongo-server:
        nmap:
        parser:
        client:
          stdin_open: true
          build:
            context: reactApp
            dockerfile: dockerfile.dev
          volumes:
            - ./reactApp:/usr/src/app
            - /usr/src/app/node_modules
          ports:
            - 3000:3000
    
          

💢 Backend


  ➞ tree -d
  backend:
  ├── api.js
  ├── package.json
  ├── yarn.lock
    
          
api.js

  try {
    (async function () {
      console.log(url)
      mongo.db = await mongoConnect(url)
      mongo.dbo = mongo.db.db('mydb')
    })()
  } catch (e) {
    console.log(e)
  }
            
api.js

  const mongoGet = async () => {
    return new Promise(function (yes, no) {
      try {
        mongo.dbo.collection('scans').findOne({}, function (err, res) {
          if (err) throw err
          yes(res)
        })
      } catch (err) {
        console.log('ERROR mongo SET', err)
        no(err)
      }
    })
  }
            
api.js

    const express = require('express')        
    const app = express()

    app.get('/', function (req, res) {
      res.send('Working !!!')
    })
    
    app.get('/api/get', async function (req, res) {
      const data = await mongoGet()
      res.json(data)
    })
    
    app.listen(port, function () {
      console.log('listening on port ' + port)
    })

            
dockerfile

            FROM node:latest
            RUN mkdir -p /usr/src/app
            WORKDIR /usr/src/app
            COPY package.json .
            RUN yarn install
            COPY api.js .
            CMD ["node" ,"api.js" ]
    
            
docker-compose

version: '3'
volumes:
  mongoVolume:
  sharedFolder:

services:
  mongo-server:
  nmap:
  parser:
  client:
  backend:
    build: backend/.
    restart: always
    ports:
      - 8080:8080
    environment:
      - MONGO_HOST=mongo-server
    
            

  ➞ d ps
  CONTAINER ID        IMAGE                 STATUS              PORTS                      NAMES
  1d3c1e418da5        scanproject_backend   Up 10 seconds       0.0.0.0:8080->8080/tcp     scanproject_backend_1
  8dd524031b31        mongo                 Up 10 seconds       0.0.0.0:27017->27017/tcp   scanproject_mongo-server_1
          

Full Stack Docker Dev Env

NMAP
CLIENT
👉
👉
PARSER
👉
DB
👉
BACKEND
Back to the ⚛️ Client
list.js
card.js
list.js




import React, { useEffect, useState } from 'react'
import Card from '../src/card'

export default () => {
  const [cards, setCards] = useState([])
  useEffect(() => {
    fetch(`some/url/for/api`)
      .then((r) => r.json())
      .then((d) =>  setCards(d.nmaprun.host))
  }, [])

  return (
    
{cards.map((item,index) => ( ))}
) }
list.js


    fetch(`some/url/for/api`)
      .then((r) => r.json())
      .then((d) =>  setCards(d.nmaprun.host))


  ➞ docker-compose up backend client mongo-server

  Creating network "scanproject_default" with the default driver
  Creating scanproject_backend_1      ... done
  Creating scanproject_mongo-server_1 ... done
  Creating scanproject_client_1       ... done

    ➞ d ps
  CONTAINER ID        IMAGE                 PORTS                      NAMES
  33d8f527948c        scanproject_client    0.0.0.0:3000->3000/tcp     scanproject_client_1
  7372f0d9718e        mongo                 0.0.0.0:27017->27017/tcp   scanproject_mongo-server_1
  02bcb6671f60        scanproject_backend   0.0.0.0:8080->8080/tcp     scanproject_backend_1
  
list.js

const host =  global.process.env.api || 'localhost'

fetch(`http:${host}:8080/api/get`)
.then((r) => r.json())
.then((d) =>  setCards(d.nmaprun.host))

➞ d run -v sharedFolder:/usr/src/app/data nmap

Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-04 20:41 UTC
Nmap scan report for ksp.co.il (212.199.38.38)
Host is up (0.0031s latency).
rDNS record for 212.199.38.38: 212.199.38.38.hosting.spd.co.il
Not shown: 998 filtered ports
PORT    STATE SERVICE
80/tcp  open  http
443/tcp open  https

Nmap scan report for ivory.co.il (80.178.161.201)
Host is up (0.0027s latency).
Other addresses for ivory.co.il (not scanned): 212.199.184.138
rDNS record for 80.178.161.201: 80.178.161.201.static.hosting.spd.co.il
Not shown: 998 filtered ports
PORT    STATE SERVICE
80/tcp  open  http
443/tcp open  https

Nmap done: 2 IP addresses (2 hosts up) scanned in 11.16 seconds
    
docker-compose.js

  version: '3'
  volumes:
    mongoVolume:
    sharedFolder:
  
  services:
    mongo-server:
      image: 'mongo'
      restart: always
      volumes:
        - mongoVolume:/data/db
      ports:
        - 27017:27017
    nmap:
      build: nmap/.
      restart: always
      volumes:
        - sharedFolder:/usr/src/app/data
    parser:
      build: parser/.
      restart: always
      volumes:
        - sharedFolder:/usr/src/app/data
      environment:
        - MONGO_HOST=mongo-server
    client:
      stdin_open: true
      build:
        context: reactApp
        dockerfile: dockerfile.dev
      volumes:
        - ./reactApp:/usr/src/app
        - /usr/src/app/node_modules
      ports:
        - 3000:3000
    backend:
      build: backend/.
      restart: always
      ports:
        - 8080:8080
      environment:
        - MONGO_HOST=mongo-server
  

Full Stack Docker Dev Env
NMAP
CLIENT
👉
👉
PARSER
👉
DB
👉
BACKEND

Why?

  • Runs on my machine = runs anywhere
  • New team productive from day 1
  • language free - database free
  • Isolated env
  • Clean env
  • Sharable env
  • Scalable env
  • Maintainable env

😎

Production Containers


  ➞ yarn build
  yarn run v1.21.1
  warning ../../../../../../../package.json: No license field
  $ react-scripts build
  Creating an optimized production build...

  Compiled successfully.

  File sizes after gzip:

  39.77 KB  build/static/js/2.312ef41f.chunk.js
  1.01 KB   build/static/js/main.8295d4ee.chunk.js
  773 B     build/static/js/runtime-main.815af2bc.js
  743 B     build/static/css/main.c57ac939.chunk.css

 

  ➞ tree build

    build:
    ├── asset-manifest.json
    ├── favicon.ico
    ├── index.html
    ├── logo192.png
    ├── logo512.png
    ├── manifest.json
    ├── precache-manifest.4334ca6cc0765e299ad636302f210bd4.js
    ├── robots.txt
    ├── service-worker.js
    └── static
        ├── css
        │   ├── main.c57ac939.chunk.css
        │   └── main.c57ac939.chunk.css.map
        ├── js
        │   ├── 2.312ef41f.chunk.js
        │   ├── 2.312ef41f.chunk.js.LICENSE.txt
        │   ├── 2.312ef41f.chunk.js.map
        │   ├── main.8295d4ee.chunk.js
        │   ├── main.8295d4ee.chunk.js.map
        │   ├── runtime-main.815af2bc.js
        │   └── runtime-main.815af2bc.js.map
        └── media
            └── logo.5d5d9eef.svg

    4 directories, 19 files

Multi-Step Build
 

  FROM node:latest as builder
  RUN mkdir -p /usr/src/app
  WORKDIR /usr/src/app
  COPY package.json .
  RUN yarn install
  EXPOSE 3000
  COPY . .
  RUN yarn build
  
  FROM navikt/node-express
  COPY --from=builder /app/build /to/the/folder/of/your/web-server

Multi-Step Build AWS Ready
 

  FROM node:latest
  RUN mkdir -p /usr/src/app
  WORKDIR /usr/src/app
  COPY package.json .
  RUN yarn install
  EXPOSE 3000
  COPY . .
  RUN yarn build
  
  FROM navikt/node-express
  COPY --from=0 /app/build /to/the/folder/of/your/web-server

sphera
to be continued