No Description

Frederic G. MARAND bf8ee1f9f8 Step 5: persistence using a bound volume. 6 years ago
nginx 43bf980d17 First commit: basic intro, create a custom Nginx images using a Dockerfile. 6 years ago
node bf8ee1f9f8 Step 5: persistence using a bound volume. 6 years ago
postgres bf8ee1f9f8 Step 5: persistence using a bound volume. 6 years ago
.gitignore bf8ee1f9f8 Step 5: persistence using a bound volume. 6 years ago
Dockerfile 43bf980d17 First commit: basic intro, create a custom Nginx images using a Dockerfile. 6 years ago
README.md bf8ee1f9f8 Step 5: persistence using a bound volume. 6 years ago

README.md

From https://www.codeschool.com/screencasts/build-a-node-app-with-postgres-and-docker

Step 1: Nginx

  • Run nginx

    • in foreground
      • docker run -p 81:80 --name web nginx
    • in foreground and removing it when stopped
      • docker run -p 81:80 --name web --rm nginx
    • in background
      • docker run -p 81:80 --name web -d nginx
    • foreground, mounting the nginx/html directory:

      docker run --rm \
      -p 81:80      \
      --name web    \
      --mount type=bind,source="$PWD"/nginx/html,target=/usr/share/nginx/html \
      nginx
      
      # or...
      
      docker run --rm                              \
      -p 81:80                                   \
      --name web                                 \
      -v "$PWD"/nginx/html,/usr/share/nginx/html \
      nginx
      
  • Enter the container: docker exec -it web /bin/bash

  • Build a local image from the Dockerfile

    docker build -t osinet/nginx:latest .
    
  • Run the newly built image:

    docker run --rm \
    -p 81:80 \
    --name web \
    --mount type=bind,source=$PWD/nginx/html,target=/usr/share/nginx/html \ 
    osinet/nginx
    
  • List images

    • All except intermediates: docker images
    • All including intermediates: docker images -a
    • Images with this name: docker images osinet/nginx

Step 2: Node.js app

mkdir node
cd node
# edit Dockerfile
docker build -t node-app .
docker run -p 8888:8888             \
  -v $PWD/node/src:/usr/src/app/src \ 
  --name voting-node                \
  --rm                              \
  node-app 

Step 3: PostgreSQL

  • Build and run the container

    mkdir postgres
    cd postgres
    # edit Dockerfile
    docker build -t voting-pg .
    docker run -p 5432:5432             \
    --name voting-pg                  \
    --rm                              \
    voting-pg
    
  • Enter the container with a PG client:

    # Without the -U, PG will try to use undeclared used root.  
    docker container exec -it voting-pg psql -U postgres
    
  • In psql in the container, list databases, create table, list tables:

    \l
    
    CREATE TABLE votes (
    id INTEGER PRIMARY KEY,
    number_of_votes INTEGER,
    option_name VARCHAR(20)
    );
    
    \dt
    
    • Now we have a table:

       List of relations
      Schema | Name  | Type  |  Owner
      --------+-------+-------+----------
      public | votes | table | postgres
      (1 row)
      
    • Insert initial data

      INSERT INTO votes (id, number_of_votes, option_name) VALUES (1, 13, 'sandwiches');
      INSERT INTO votes (id, number_of_votes, option_name) VALUES (2, 21, 'tacos');
      SELECT * FROM votes;
      
    • Results:

      id | number_of_votes | option_name
      ----+-----------------+-------------
      1 |               0 | sandwiches
      2 |               0 | tacos
      (2 rows)
      

Step 4: PG in Node app

  • To reach PG, the app needs to know the address. To get to it from inside the container where the app runs, look for the gateway value in the results of docker bridge:

    [...snip...]
    "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
    [...snip...]
    
  • We then know that the IP to use in client.connect() will be 172.17.0.1, at least in the current configuration. Will probably have to come from the outside for more flexibility.

  • Posting data to update:

    curl -d"yourVote=sandwiches" http://localhost:8888/vote
    curl -d"yourVote=tacos"      http://localhost:8888/vote
    curl -d"yourVote=invalid"    http://localhost:8888/vote
    

Step 5: persistence

  • Initialize PG as described on the image page, by adding a SQL file to the container from the host into the docker-entrypoint-initdb.d/ directory.

    COPY seed.sql /docker-entrypoint-initdb.d/

  • Redefine the image-provided volume pointing to the PG data:

    VOLUME /var/lib/postgresql/data

  • Rebuild container

    cd postgres docker container build -t voting-pg .

  • Run it. Beware: we can't have a .gitkeep in the postgres/data directory, which will prevent PG from starting in that directory. But if we don't have it, the directory will have to be created, because git won't save it.

    cd postgres
    if [ ! -d data ]; then mkdir data fi
    docker container run  \ 
    --name voting-pg    \
    -p 9000:5432        \
    -v $PWD/data:/var/lig/postgresql/data \
    --rm -d             \
    voting-pg
    
    
  • Run the app

    cd node
    docker container run  \
    --name voting-node  \
    -p 8888:8888        \ 
    -v $PWD/src:/usr/src/app/src \
    --rm -d             \
    voting-node
    
  • When stopping the PG container, the node app will crash and not restart. Just touch the server.js file and nodemon in the node container will restart it. This is only good for a development workflow: a production version should handle disconnects.