ops__codeschool-docker-nodeapp/README.md

187 lines
4.8 KiB
Markdown

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:
```bash
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`
```bash
docker build -t osinet/nginx:latest .
```
* Run the newly built image:
```bash
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
```bash
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
```bash
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:
```bash
# 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:
```postgresql
\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
```postgresql
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:
```bash
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.
```bash
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
```bash
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.