|
| 1 | +## `docker` Flavor |
| 2 | +This flavor of the pal boilerplate is designed to get someone up and running |
| 3 | +using Docker with scalable best practices. Certain features require the `deployment` |
| 4 | +flavor of the pal boilerplate to be installed as well in order to function. |
| 5 | + |
| 6 | +## Basics |
| 7 | +This [Dockerfile](./server/Dockerfile) uses |
| 8 | +[multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/) |
| 9 | +to create different Docker images depending on the environment the images will |
| 10 | +be running in, while ensuring best practices are followed to keep image size low |
| 11 | +and create a security sandbox if you are running a server. |
| 12 | + |
| 13 | +We are using Docker Compose to define `web` and `test` services. The `web` wervice uses |
| 14 | +the `release` Dockerfile stage, and the `test` service uses the `test` Dockerfile stage. |
| 15 | + |
| 16 | +### `docker-compose.yml` Services |
| 17 | +The `docker-compose.yml` file defines four services. The reason for the `*_base` services |
| 18 | +is that certain CI providers like CircleCI do not support voluming in files, and you will |
| 19 | +get strange file system errors if you try to run with a `volumes` block. |
| 20 | + |
| 21 | +#### `web_base` |
| 22 | +All configuration for running the webserver locally, minus the `volumes` block. |
| 23 | + |
| 24 | +#### `web` |
| 25 | +`web_base`, plus the `volumes` block required for hotreloading to function locally. |
| 26 | + |
| 27 | +#### `test_base` |
| 28 | +All configuration for running the tests, minus the `volumes` block. |
| 29 | + |
| 30 | +#### `test` |
| 31 | +`test_base`, plus the `volumes` block required to allow re-running tests in |
| 32 | +`watch` mode or by hand, but without requiring a full image rebuild. |
| 33 | + |
| 34 | +### Commands |
| 35 | + |
| 36 | +#### `npm run build:test` |
| 37 | +Rebuilds the `test` service used for running tests, and will re-install npm |
| 38 | +dependencies when they change. |
| 39 | + |
| 40 | +#### `npm run build:web` |
| 41 | +Rebuilds the `web` service used locally, and will re-install npm dependencies when |
| 42 | +they change. |
| 43 | + |
| 44 | +#### `npm run docker:lint` |
| 45 | +Runs the `npm run lint` command in the `test` service. |
| 46 | + |
| 47 | +#### `npm run docker:start` |
| 48 | +Starts the `web` service in daemon mode, making it available at `localhost:3000`. |
| 49 | + |
| 50 | +#### `npm run docker:test` |
| 51 | +Runs the `npm test` command in the `test` service. |
| 52 | + |
| 53 | +#### `npm run docker:test:ci` |
| 54 | +Starts the `test_base` service, which triggers both a `lint` and `test` npm script |
| 55 | +run. The process will exit with the same code the internal process exits with, |
| 56 | +making this the ideal command to use when integrating with CI. |
| 57 | + |
| 58 | +### `.env` |
| 59 | +This flavor no longer uses `.env` files, as it is safer to start the container declaring |
| 60 | +the environment variables in either the `docker-compose.yml` file or via the `docker` cli. |
| 61 | + |
| 62 | +If you need to add any environment variables, you can do so in the `docker-compose.yml` |
| 63 | +files as shown, or add them to `.env` and load them in as shown |
| 64 | +[here](https://docs.docker.com/compose/compose-file/#env_file). |
| 65 | + |
| 66 | +### Stages |
| 67 | +There are currently four stages in the Dockerfile that are used. |
| 68 | + |
| 69 | +#### `base` |
| 70 | +Contains all package installs, files system modifications, and entrypoint declaration. |
| 71 | +Any commands that will not change across the other stages or are required for multiple |
| 72 | +other stages to execute properly should be put in this stage. |
| 73 | + |
| 74 | +#### `dependencies` |
| 75 | +The `dependencies` stage is used to install npm dependencies, copy all of your source |
| 76 | +files, and then optionally run any build commands that need to be executed. The desired |
| 77 | +outcome of this stage is an image that contains all dependencies, all source files, and |
| 78 | +all built assets (if necessary). |
| 79 | + |
| 80 | +In order to run build scripts, you will need to locate this stage in the Dockerfile |
| 81 | +and uncomment the `RUN npm run build` command that is in there, possibly changing the |
| 82 | +command if you are using multiple build scripts in your `package.json`. |
| 83 | + |
| 84 | +#### `test` |
| 85 | +The `test` stage is used for running your test suite. It changes the user to `node` |
| 86 | +to mimic the production environment, and then runs `npm lint && npm test` which should |
| 87 | +run your full test suite. The container will exit with the same code as your test |
| 88 | +runner, which means that in CI you can run `npm run docker:test:ci` as your test step to |
| 89 | +automatically build your test image and then run your tests inside of it. |
| 90 | + |
| 91 | +#### `development` |
| 92 | +The `development` stage is meant to run your server locally with dev deps installed. The |
| 93 | +`docker-compose.yml` file can be used to tweak the environment variables used for |
| 94 | +this stage when running locally, and the logic for building this stage should not |
| 95 | +make any assumptions about what environment the output will be used in. |
| 96 | + |
| 97 | +#### `release` |
| 98 | +The `release` stage is meant to run your server in a production-like setup without dev deps. |
| 99 | +The `docker-compose.yml` file can be used to tweak the environment variables used for |
| 100 | +this stage when running locally, and the logic for building this stage should not |
| 101 | +make any assumptions about what environment the output will be used in. |
| 102 | + |
| 103 | +## Local Development |
| 104 | +If you are using the `development` flavor alongside this `docker` flavor, you can simply |
| 105 | +run `npm run docker:start` to build the release stage of the Dockerfile, and then start |
| 106 | +it as a `daemon` in Docker. You can then visit `localhost:3000` to hit your server. |
| 107 | + |
| 108 | +By default, the server is started using `nodemon` when you start it using |
| 109 | +`docker-compose`, which means every time you save a file the server will be restarted |
| 110 | +automatically with your fresh changes. |
| 111 | + |
| 112 | +### Running Tests |
| 113 | +Running tests locally is extremely easy. Simply run `npm run docker:test`, and linting |
| 114 | +and testing will be run. If you modify the `package*.json` files, you will need to run |
| 115 | +`npm run build:test` to trigger a reinstall of your dependencies. |
| 116 | + |
| 117 | +### Secret Management (`.env`) |
| 118 | +This removes the option to have a `.env` files for secrets locally, because those environment |
| 119 | +variables can now just be set in the `docker-compose.yml` file `environment` section. If |
| 120 | +you have true secrets that you need locally and cannot check into Git, you can re-create |
| 121 | +the `server/.env` file, and then add a key in the `*_base` services in `docker-compose.yml` |
| 122 | +that is simply `env_file: server/.env` at the same level in the yaml as the `environment` key. |
| 123 | + |
| 124 | +## Changing the Port |
| 125 | +Currently the build process assumes that the port default of `3000` in |
| 126 | +`server/manifest.js` is being used. `server/Dockerfile` has an `EXPOSE` command that |
| 127 | +references this port, and `docker-compose.yml` also contains a mapping of port `3000` |
| 128 | +in the container to port `3000` on the host machine. |
0 commit comments