Experimenting with docker and configuration

This commit is contained in:
2021-02-04 20:52:09 +11:00
parent a1c76a23be
commit e5a81c79e1
8 changed files with 281 additions and 14 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ MAIL_SMTP=smtp.example.com
MAIL_USERNAME=foobar@example.com MAIL_USERNAME=foobar@example.com
MAIL_PASSWORD=foobar MAIL_PASSWORD=foobar
DB_HOSTADDR=127.0.0.1 DB_HOSTNAME=127.0.0.1
DB_DATABASE=template DB_DATABASE=template
DB_USERNAME=template DB_USERNAME=template
DB_PASSWORD=pikachu DB_PASSWORD=pikachu
+1
View File
@@ -109,3 +109,4 @@ public/*.js
public/*.css public/*.css
public/*.map public/*.map
public/*.gz public/*.gz
docker-compose.yml
+18
View File
@@ -0,0 +1,18 @@
FROM node:15
# Change working directory
WORKDIR "/app"
# Copy package.json and package-lock.json
COPY package*.json ./
# Install npm production packages
RUN npm install
COPY . /app
EXPOSE 3000
USER node
ENTRYPOINT ["npm", "start"]
+9 -10
View File
@@ -16,9 +16,15 @@ To set up this template, please ensure mariadb is running on the host computer,
This should get the template working in development mode. This should get the template working in development mode.
# Deployment # Setup Deployment
When deploying your project, please ensure that you're using HTTPS protocol. It's not hard to set up using [certbot](https://certbot.eff.org/). Eventually, a clean install will be this easy:
```
git clone template-url
npm run configure
docker-compose up
```
# Microservices # Microservices
@@ -54,14 +60,7 @@ TODO: more info.
- configuration script - configuration script
- Docker, docker, docker. - Docker, docker, docker.
- Start here page - Start here page
- LICENSE
Eventually, a clean install will be this easy:
```
git clone template-url
npm run configure
npm start
```
# Email settings # Email settings
+248
View File
@@ -0,0 +1,248 @@
//setup
const readline = require('readline');
const fs = require('fs');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
//manually promisify this (util didn't work)
const question = (prompt, def) => {
return new Promise((resolve, reject) => {
rl.question(`${prompt} (${def}): `, answer => {
resolve(answer || def);
});
});
};
//questions
(async () => {
//project configuration
const projectName = await question('Project Name', 'template');
const projectWebAddress = await question('Project Web Address', 'example.com');
const projectMailSMTP = await question('Project Mail SMTP', 'smtp.example.com');
const projectMailUser = await question('Project Mail Username', 'foobar@example.com');
const projectMailPass = await question('Project Mail Password', 'foobar');
const projectDBUser = await question('Project Database Username', projectName);
const projectDBPass = await question('Project Database Password', 'pikachu');
//news configuration
const newsName = await question('News Name', 'news');
const newsDBUser = await question('News Database Username', newsName);
const newsDBPass = await question('News Database Password', 'charizard');
const newsKey = await question('News Query Key', 'key');
//TODO: chat configuration
//database configuration
const databaseRootPassword = await question('Database Root Password', 'password');
const databaseTimeZone = await question('Database Timezone', 'Australia/Sydney');
//traefic configuration
const supportEmail = await question('Support Email', 'postmaster@example.com');
const yml = `
services:
${projectName}:
build: .
ports:
- "3000:3000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.${projectName}router.rule=Host('${projectWebAddress}')"
- "traefik.http.routers.${projectName}router.entrypoints=websecure"
- "traefik.http.routers.${projectName}router.tls.certresolver=myresolver"
- "traefik.http.routers.${projectName}router.service=${projectName}service@docker"
- "traefik.http.services.${projectName}service.loadbalancer.server.port=3000"
environment:
- WEB_PROTOCOL=https
- WEB_ADDRESS=localhost
- WEB_PORT=3000
- MAIL_SMTP=${projectMailSMTP}
- MAIL_USERNAME=${projectMailUser}
- MAIL_PASSWORD=${projectMailPass}
- DB_HOSTNAME=database
- DB_DATABASE=${projectName}
- DB_USERNAME=${projectDBUser}
- DB_PASSWORD=${projectDBPass}
- DB_TIMEZONE=${databaseTimeZone}
- SESSION_SECRET=secret
- SESSION_ADMIN=adminsecret
- NEWS_URI=http://news:3100/news
- NEWS_KEY=${newsKey}
networks:
- app-network
depends_on:
- database
news:
image: krgamestudios/news-server:v1.0.0
ports:
- "3100:3100"
labels:
- "traefik.enable=true"
- "traefik.http.routers.newsrouter.rule=Host('${projectWebAddress}')"
- "traefik.http.routers.newsrouter.entrypoints=websecure"
- "traefik.http.routers.newsrouter.tls.certresolver=myresolver"
- "traefik.http.routers.newsrouter.service=newsservice@docker"
- "traefik.http.services.newsservice.loadbalancer.server.port=3100"
environment:
- WEB_PORT=3100
- DB_HOSTNAME=database
- DB_DATABASE=news
- DB_USERNAME=${newsDBUser}
- DB_PASSWORD=${newsDBPass}
- DB_TIMEZONE=${databaseTimeZone}
- QUERY_LIMIT=10
- QUERY_KEY=${newsKey}
networks:
- app-network
depends_on:
- database
#chat:
# image: krgamestudios/chat-server
# ports:
# - "3200:3200"
database:
image: mariadb
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${databaseRootPassword}
volumes:
- ./mysql:/var/lib/mysql
networks:
- app-network
traefik:
image: "traefik:v2.4"
container_name: "traefik"
command: >
- "--api.insecure=false"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=${supportEmail}
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- app-network
networks:
app-network:
driver: bridge
`;
fs.writeFileSync('docker-compose.yml', yml);
})()
.then(() => rl.close())
.catch(e => console.error(e))
;
/* Default below
services:
template:
build: .
ports:
- "3000:3000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.templaterouter.rule=Host('template.com')"
- "traefik.http.routers.templaterouter.entrypoints=websecure"
- "traefik.http.routers.templaterouter.tls.certresolver=myresolver"
- "traefik.http.routers.templaterouter.service=templateservice@docker"
- "traefik.http.services.templateservice.loadbalancer.server.port=3000"
environment:
- WEB_PROTOCOL=https
- WEB_ADDRESS=localhost
- WEB_PORT=3000
- MAIL_SMTP=smtp.example.com
- MAIL_USERNAME=foobar@example.com
- MAIL_PASSWORD=foobar
- DB_HOSTNAME=database
- DB_DATABASE=template
- DB_USERNAME=template
- DB_PASSWORD=pikachu
- DB_TIMEZONE=Australia/Sydney
- SESSION_SECRET=secret
- SESSION_ADMIN=adminsecret
networks:
- app-network
depends_on:
- database
news:
image: krgamestudios/news-server:v1.0.0
ports:
- "3100:3100"
labels:
- "traefik.enable=true"
- "traefik.http.routers.newsrouter.rule=Host('template.com')"
- "traefik.http.routers.newsrouter.entrypoints=websecure"
- "traefik.http.routers.newsrouter.tls.certresolver=myresolver"
- "traefik.http.routers.newsrouter.service=newsservice@docker"
- "traefik.http.services.newsservice.loadbalancer.server.port=3100"
environment:
- WEB_PORT=3100
- DB_HOSTNAME=database
- DB_DATABASE=news
- DB_USERNAME=news
- DB_PASSWORD=charizard
- DB_TIMEZONE=Australia/Sydney
- QUERY_LIMIT=10
- QUERY_KEY=key
networks:
- app-network
depends_on:
- database
#chat:
# image: krgamestudios/chat-server
# ports:
# - "3200:3200"
database:
image: mariadb
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- ./mysql:/var/lib/mysql
networks:
- app-network
traefik:
image: "traefik:v2.4"
container_name: "traefik"
command:
- "--api.insecure=false"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=postmaster@example.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- app-network
networks:
app-network:
driver: bridge
*/
+1
View File
@@ -4,6 +4,7 @@
"description": "A website template using the MERN stack.", "description": "A website template using the MERN stack.",
"main": "server/server.js", "main": "server/server.js",
"scripts": { "scripts": {
"configure": "node configure-script.js",
"start": "npm run build && node server/server.js", "start": "npm run build && node server/server.js",
"build": "npm run build:server && npm run build:client", "build": "npm run build:server && npm run build:client",
"build:server": "exit 0", "build:server": "exit 0",
+1 -1
View File
@@ -1,7 +1,7 @@
const Sequelize = require('sequelize'); const Sequelize = require('sequelize');
const sequelize = new Sequelize(process.env.DB_DATABASE, process.env.DB_USERNAME, process.env.DB_PASSWORD, { const sequelize = new Sequelize(process.env.DB_DATABASE, process.env.DB_USERNAME, process.env.DB_PASSWORD, {
host: process.env.DB_HOSTADDR, host: process.env.DB_HOSTNAME,
dialect: 'mariadb', dialect: 'mariadb',
timezone: process.env.DB_TIMEZONE, timezone: process.env.DB_TIMEZONE,
logging: false logging: false
+2 -2
View File
@@ -42,8 +42,8 @@ module.exports = ({ production, analyzer }) => {
plugins: [ plugins: [
new DefinePlugin({ new DefinePlugin({
'process.env': { 'process.env': {
'NEWS_URI': '"http://dev-news.eggtrainer.com:3100/news"', 'NEWS_URI': production ? `${process.env.NEWS_KEY}` : '"http://dev-news.eggtrainer.com:3100/news"',
'NEWS_KEY': '"key"', 'NEWS_KEY': production ? `${process.env.NEWS_KEY}` : 'key',
} }
}), }),
new CleanWebpackPlugin({ new CleanWebpackPlugin({