There are two options how to run application. Develop and deploy mode.
Both modes are using same docker volume (same database is loaded).
.env.example a .envclient/.env.development.example a client/.env.development Si desea ejecutar la aplicación en modo de desarrolloclient/.env.production.example a client/.env.production Si desea ejecutar la aplicación en modo de producción${REACT_APP_GOOGLE_API} Sigue estos pasos This will just run db and pgadmin containers. React and server instances are running separately, outside of containers.
${DB_HOST} de .env a: localhostdocker-compose -f docker-compose.dev.yml up -dnpm i && npm run server${REACT_APP_BASE_URL} variable en el archivo de client/.env.development en consecuencia a ${SERVER_PORT} especificado en el archivo .envcd client && npm i && cd .. && npm run clientlocalhost:3000 This will run db, pgadmin, server and build react with disabled redux devtools.
${DB_HOST} de .env a postgres .docker-compose up -d .localhost:${SERVER_PORT} .Para el funcionamiento correcto de la aplicación, la base de datos debe poblarse primero. Utilizaremos la línea de comandos para lograr eso.
Desde el directorio raíz, navegue hasta el directorio donde se encuentran los datos exportados.
cd dummy Luego, copie los datos en ejecutar el contenedor Postgres (para el modo de desarrollo, use dev_postgres_container ).
docker cp dbexport.sql postgres_container:/
Luego, ingrese el contenedor (para modo de desarrollo, use dev_postgres_container ).
docker exec -it postgres_container /bin/bash
Si desea importar datos en una base de datos ya poblada, primero debe eliminar la tabla existente y luego crear uno nuevo. En Container Console, suelte la base de datos existente. (omita este paso si aún no ha creado una base de datos)
dropdb -U ${DB_USER} ${DB_NAME}Inicie sesión en el servidor Postgres como usuario.
su - ${DB_USER}Luego cree una nueva base de datos.
createdb ${DB_NAME}Salir de la consola del servidor Postgres.
exitUbulló la base de datos con nuevos datos.
psql -d ${DB_NAME} -U ${DB_USER} -f dbexport.sql Ahora puede iniciar sesión en la aplicación. Tanto name predeterminado como password son: admin .
localhost:${DB_PORT}${DB_USER}${DB_PASSWORD}http://localhost:${PGADMIN_PORT}${PGADMIN_EMAIL}${PGADMIN_PASSWORD}postgres${DB_PORT}${DB_NAME}${DB_PASSWORD} El archivo Docker se encuentra a nivel raíz del proyecto y se usa solo para el modo de implementación.
# Dockerfile
FROM node:latest
WORKDIR /server
COPY . ./
RUN npm install
RUN npm install --prefix client
CMD npm run build Al principio, el último nodo se descarga y el directorio de trabajo /server se crea en un contenedor recién creado. En este directorio de trabajo, se copia el código fuente completo, espere que los archivos especificados en client/.dockerignore . Se omiten estos archivos. Luego, las dependencias de nodo se instalan en el directorio de trabajo para las instancías de servidor y cliente. Por último, se llama el comando npm run build que se encuentra en package.json . Este comando construye primero la aplicación React y luego dispara el servidor. Cuando el servidor se inicia de esta manera, la variable de entorno NODE_ENV se establece en production y se utiliza la versión creada de la aplicación React.
Estamos utilizando dos archivos Docker-Compose. docker-compose.dev.yml para el modo de desarrollo y docker-compose.yml para el modo de producción, ambos ubicados en el directorio raíz. Cada archivo de composición carga variables de entorno especificadas en el archivo .env .
# docker-compose.dev.yml
version : " 3.5 "
# inspired by https://github.com/khezen/compose-postgres
services :
postgres :
container_name : postgres_container
image : postgres:11
environment :
POSTGRES_USER : ${DB_USER}
POSTGRES_PASSWORD : ${DB_PASSWORD}
PGDATA : /data/postgres
volumes :
- postgres:/data/postgres
ports :
- " ${DB_PORT}:5432 "
networks :
- postgres
restart : always
pgadmin :
container_name : pgadmin_container
image : dpage/pgadmin4
environment :
PGADMIN_DEFAULT_EMAIL : ${PGADMIN_EMAIL}
PGADMIN_DEFAULT_PASSWORD : ${PGADMIN_PASSWORD}
PGADMIN_CONFIG_SERVER_MODE : " False "
volumes :
- pgadmin:/root/.pgadmin
ports :
- " ${PGADMIN_PORT}:80 "
networks :
- postgres
restart : always
server :
container_name : server_container
build :
context : .
dockerfile : Dockerfile
depends_on :
- postgres
ports :
- " ${SERVER_PORT}:${SERVER_PORT} "
networks :
- postgres
restart : always
networks :
postgres :
driver : bridge
volumes :
postgres :
pgadmin : Esta configuración de composición crea 3 contenedores, 1 red y 1 volumen para almacenar datos persistentes. Cada contenedor está utilizando la misma red para la comunicación con otros contenedores. Cada contenedor, después de la falla, se reinicia automáticamente. Container postgres_container crea un servidor PostgreSQL, donde los datos persistentes se almacenan en volumen. También hay contenedor pgadmin_container , que es el cliente SQL. El último contenedor, llamado server_container , es donde se está ejecutando nuestra aplicación principal. En lugar de la imagen, está utilizando la compilación, definida en DockerFile, discutida en la sección anterior.
La configuración de composición para el modo de desarrollo es muy similar a una para el modo de implementación. La única diferencia es que no hay server_container , porque el servidor y el cliente son instancias separadas que se quedan fuera de Docker.
.env.example a .env y establezca un valor de ${DB_HOST} a postgres .client/.env.production.example al client/.env.production .${REACT_APP_GOOGLE_API} en client/.env.production , siga estos pasos. El proxy inverso debe configurarse para reenviar el acceso a Jenkins y el servidor de aplicaciones. Los puertos especificados en ./env tienen que coincidir con los de la configuración de proxy inversa nginx.
Primero, navegue al directorio de configuración de sitios disponible.
cd /etc/nginx/sites-available/ Crear archivo de configuración. Puedes nombrarlo como tú, whish. La buena práctica es nombrarlo de la misma manera que es su dirección DNS. En nuestro caso, es lora.fiit.stuba.sk .
touch lora.fiit.stuba.sk Copie y pegue el siguiente código al archivo recién creado. Cambie la configuración de proxy_pass para cada ubicación para que coincidan con los puertos especificados en .env . No olvides ajustar también server_name para que coincida con tu DNS.
upstream jenkins {
keepalive 32; # keepalive connections
server 127.0.0.1:8080; # jenkins ip and port
}
# Required for Jenkins websocket agents
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name lora.fiit.stuba.sk www.lora.fiit.stuba.sk;
# this is the jenkins web root directory
# (mentioned in the /etc/default/jenkins file)
root /var/run/jenkins/war/;
access_log /var/log/nginx/jenkins/access.log;
error_log /var/log/nginx/jenkins/error.log;
# pass through headers from Jenkins that Nginx considers invalid
ignore_invalid_headers off;
location /jenkins/ {
autoindex on ;
sendfile off ;
proxy_pass http://jenkins/jenkins/;
proxy_redirect default ;
proxy_http_version 1.1 ;
# Required for Jenkins websocket agents
proxy_set_header Connection $connection_upgrade ;
proxy_set_header Upgrade $http_upgrade ;
proxy_set_header Host $host ;
proxy_set_header X-Real-IP $remote_addr ;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $scheme ;
proxy_max_temp_file_size 0 ;
#this is the maximum upload size
client_max_body_size 10m ;
client_body_buffer_size 128k ;
proxy_connect_timeout 90 ;
proxy_send_timeout 90 ;
proxy_read_timeout 90 ;
proxy_buffering off ;
proxy_request_buffering off; # Required for HTTP CLI commands
proxy_set_header Connection "" ; # Clear for keepalive
}
location / {
#Add serving gzipped files
gzip_static on ;
gzip on ;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 256 ;
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
application/xml+rss text/javascript
application/atom+xml
application/geo+json
application/x-javascript
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/xhtml+xml
font/eot
font/otf
font/ttf
image/svg+xml;
proxy_pass http://127.0.0.1:5000/;
proxy_set_header Host $host ;
proxy_set_header X-Real-IP $remote_addr ;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $scheme ;
# enable WebSockets
proxy_http_version 1.1 ;
proxy_set_header Upgrade $http_upgrade ;
proxy_set_header Connection "upgrade" ;
}
listen 443 ssl; # managed by Certbot
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/lora.fiit.stuba.sk/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/lora.fiit.stuba.sk/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
# SSL redirect from HTTP to HTTPS
server {
if ( $host = lora.fiit.stuba.sk) {
return 301 https:// $host$request_uri ;
} # managed by Certbot
listen 80 ;
server_name lora.fiit.stuba.sk www.lora.fiit.stuba.sk;
return 404 ; # managed by Certbot
}Guarde el archivo y reinicie el servicio Nginx
sudo systemctl restart nginx Se debe acceder a la aplicación Jenkins en lora.fiit.stuba.sk/jenkins . En su caso, sería su nombre DNS en lugar de lora.fiit.stuba.sk .
Cuando desee cambiar el hogar predeterminado para Jenkins, puede cambiar la variable JENKINS_HOME . La guía está fuertemente inspirada en este tutorial.
Cree un nuevo directorio donde quiera mover a los Jenkins a casa. En nuestro caso es /data/jenkins .
mkdir /data/jenkinsCambie la propiedad del directorio recién creado.
sudo chown jenkins:jenkins /data/jenkins Copie el contenido del Old Jenkins Home Directory, /var/lib/jenkins/ , al nuevo directorio de inicio de Jenkins, /data/jenkins/ , utilizando el siguiente comando.
sudo cp -prv /var/lib/jenkins /data/jenkins/A continuación, cambie el usuario del usuario de Jenkins.
sudo usermod -d /data/jenkins/ jenkins Actualice la nueva ruta del directorio de inicio de Jenkins en /etc/default/jenkins . Puede usar cualquier editor de su elección. En nuestro caso, estamos usando VI.
sudo vi /etc/default/jenkinsDesplácese hacia abajo hasta la ubicación de Jenkins Home y actualice la nueva ruta de directorio de inicio.
# defaults for Jenkins automation server
# pulled in from the init script; makes things easier.
NAME=jenkins
# arguments to pass to java
# Allow graphs etc. to work even when an X server is present
JAVA_ARGS= " -Djava.awt.headless=true "
# JAVA_ARGS="-Xmx256m"
# make jenkins listen on IPv4 address
# JAVA_ARGS="-Djava.net.preferIPv4Stack=true"
PIDFILE=/var/run/$NAME/$NAME.pid
# user and group to be invoked as (default to jenkins)
JENKINS_USER=$NAME
JENKINS_GROUP=$NAME
# location of the jenkins war file
JENKINS_WAR=/usr/share/$NAME/$NAME.war
# jenkins home location
JENKINS_HOME=/data/$NAME
# set this to false if you don't want Jenkins to run by itself
# in this set up, you are expected to provide a servlet container
# to host jenkins.
RUN_STANDALONE=trueInicie el servicio Jenkins utilizando el siguiente comando.
sudo service jenkins start
Visite Jenkins desde su navegador en lora.fiit.stuba.sk/jenkins .
Inicie sesión en la aplicación.
Navegue para Manage Jenkins ubicado en el lado izquierdo de la pantalla.
Haga clic en Manage Credentials ubicada en Security group .
Luego, haga clic en el enlace (global) ubicado en la tabla.
Haga clic en el botón addCredentials en el lado izquierdo de la pantalla.
Elija la opción Secret file en el menú desplegable Kind .
Cargue el archivo .env cumplido y configure el campo ID en env .
Repita el paso 6 y luego cargue el archivo client/.env.production y establezca el campo ID en envClient .
Cree otras credenciales, pero esta vez elija SSH Username with private key desde el menú desplegable. Establezca el campo ID en lora-application-server-ssh . Para obtener las claves SSH para su repositorio (donde está el código fuente del servidor de aplicaciones) siga estas instrucciones.
Desde el tablero, haga clic en el botón New Item , ubicado en el lado izquierdo de la pantalla.
Ingrese el nombre deseado, haga clic en el botón Pipeline y confirme que haga clic en el botón Aceptar
A la script de la tubería Pegar el siguiente código
node {
/*** 1 Pull new changes from git branch deploy ***/
stage ( 'Pull master branch' ) {
git credentialsId : 'lora-application-server-ssh' , url : '[email protected]:danielhros/lora-application-server.git'
}
/*** 2 Add secret enviroment variables stored securely in Jenkins ***/
stage ( 'Add enviroment variables' ) {
/* 2.1 Remove .env file if exists */
sh 'rm -f -- .env'
/* 2.2 Add .env file to server */
withCredentials ( [ file ( credentialsId : 'env' , variable : 'env' ) ] ) {
sh "cp $env ./"
}
/* 2.2 Add .env file to client */
withCredentials ( [ file ( credentialsId : 'envClient' , variable : 'envClient' ) ] ) {
sh 'cp $envClient client/.env.production'
}
}
/*** 3 Build docker image ***/
stage ( 'Build docker image' ) {
sh '(docker-compose build)'
}
/*** 4 Run docker image in production ***/
stage ( 'Run docker images' ) {
sh '(docker-compose up -d)'
}
/*** 5 Clean after build ***/
stage ( 'Clean workspace' ) {
sh 'docker system prune -f'
cleanWs ( )
}
}Guardar cambios y ejecutar su primera tubería
¡Felicidades! Después de que la tubería construya e implementa con éxito la aplicación, se puede acceder a su aplicación en lora.fiit.stuba.sk .