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 เป็น .envclient/.env.development.example เป็น client/.env.development หากคุณต้องการเรียกใช้แอพ ในโหมดพัฒนาclient/.env.production.example ตัวอย่างไปยัง client/.env.production หากคุณต้องการเรียกใช้แอพใน โหมดการผลิต${REACT_APP_GOOGLE_API} ทำตามขั้นตอนเหล่านี้ This will just run db and pgadmin containers. React and server instances are running separately, outside of containers.
${DB_HOST} จาก .env เป็น: localhostdocker-compose -f docker-compose.dev.yml up -dnpm i && npm run server${REACT_APP_BASE_URL} ตัวแปรในไฟล์ client/.env.development ตามที่ระบุไว้ที่ ${SERVER_PORT} ที่ระบุในไฟล์ .envcd client && npm i && cd .. && npm run clientlocalhost:3000 This will run db, pgadmin, server and build react with disabled redux devtools.
${DB_HOST} จาก .env เป็น postgresdocker-compose up -dlocalhost:${SERVER_PORT}สำหรับการทำงานของแอปพลิเคชันที่ถูกต้องฐานข้อมูลจะต้องมีการเติมก่อน เราจะใช้บรรทัดคำสั่งเพื่อทำสิ่งนั้นให้สำเร็จ
จากไดเรกทอรีรากนำทางไปยังไดเรกทอรีที่มีข้อมูลที่ส่งออกอยู่
cd dummy จากนั้นคัดลอกข้อมูลลงในคอนเทนเนอร์ postgres (สำหรับโหมดการพัฒนาให้ใช้ dev_postgres_container )
docker cp dbexport.sql postgres_container:/
จากนั้นป้อนคอนเทนเนอร์ (สำหรับโหมดการพัฒนาให้ใช้ dev_postgres_container )
docker exec -it postgres_container /bin/bash
หากคุณต้องการนำเข้าข้อมูลไปยังฐานข้อมูลที่มีประชากรแล้วคุณต้องลบตารางที่มีอยู่ก่อนจากนั้นสร้างใหม่ ในคอนเทนเนอร์คอนโซลวางฐานข้อมูลที่มีอยู่ (ข้ามขั้นตอนนี้หากคุณยังไม่ได้สร้างฐานข้อมูล)
dropdb -U ${DB_USER} ${DB_NAME}เข้าสู่ระบบ Postgres Server เป็นผู้ใช้
su - ${DB_USER}จากนั้นสร้างฐานข้อมูลใหม่
createdb ${DB_NAME}ออกจากคอนโซลเซิร์ฟเวอร์ Postgres
exitเติมฐานข้อมูลด้วยข้อมูลใหม่
psql -d ${DB_NAME} -U ${DB_USER} -f dbexport.sql ตอนนี้คุณสามารถเข้าสู่แอปพลิเคชัน ทั้ง name เริ่มต้นและ password คือ: admin
localhost:${DB_PORT}${DB_USER}${DB_PASSWORD}http://localhost:${PGADMIN_PORT}${PGADMIN_EMAIL}${PGADMIN_PASSWORD}postgres${DB_PORT}${DB_NAME}${DB_PASSWORD} ไฟล์ Docker อยู่ที่ระดับรูทของโครงการและใช้สำหรับโหมดการปรับใช้เท่านั้น
# Dockerfile
FROM node:latest
WORKDIR /server
COPY . ./
RUN npm install
RUN npm install --prefix client
CMD npm run build ในตอนแรกโหนดล่าสุดจะถูกดาวน์โหลดและไดเรกทอรีการทำงานของ /server ถูกสร้างขึ้นในคอนเทนเนอร์ที่สร้างขึ้นใหม่ ในไดเรกทอรีการทำงานนี้ซอร์สโค้ดทั้งหมดถูกคัดลอกคาดหวังสำหรับไฟล์ที่ระบุใน client/.dockerignore ไฟล์เหล่านี้ถูกละเว้น จากนั้นการพึ่งพาโหนดจะถูกติดตั้งลงในไดเรกทอรีการทำงานสำหรับทั้งเซิร์ฟเวอร์และไคลเอนต์ instancies สุดท้ายคำสั่ง npm run build เรียกว่าซึ่งอยู่ใน package.json คำสั่งนี้สร้างแอปพลิเคชัน React ครั้งแรกจากนั้นทริกเกอร์เซิร์ฟเวอร์ เมื่อเซิร์ฟเวอร์เริ่มต้นด้วยวิธีนี้ตัวแปรสภาพแวดล้อม NODE_ENV จะถูกตั้งค่าเป็นแอปพลิเคชัน production และเวอร์ชันที่สร้างขึ้น
เรากำลังใช้สองไฟล์ที่ใช้ Docker-compose docker-compose.dev.yml สำหรับการพัฒนาโหมดและ docker-compose.yml สำหรับโหมดการผลิตทั้งสองอยู่ในไดเรกทอรีราก แต่ละไฟล์ Compose โหลดตัวแปรสภาพแวดล้อมที่ระบุในไฟล์. .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 : การกำหนดค่านี้สร้าง 3 คอนเทนเนอร์ 1 เครือข่ายและ 1 เล่มสำหรับการจัดเก็บข้อมูลถาวร คอนเทนเนอร์ทุกแห่งใช้เครือข่ายเดียวกันสำหรับการสื่อสารกับคอนเทนเนอร์อื่น ๆ แต่ละคอนเทนเนอร์หลังจากล้มเหลวจะรีสตาร์ทโดยอัตโนมัติ คอนเทนเนอร์ postgres_container สร้างเซิร์ฟเวอร์ PostgreSQL ซึ่งข้อมูลถาวรจะถูกเก็บไว้ในระดับเสียง นอกจากนี้ยังมีคอนเทนเนอร์ pgadmin_container ซึ่งเป็นไคลเอนต์ SQL คอนเทนเนอร์ล่าสุดชื่อ server_container เป็นที่ที่แอพหลักของเรากำลังทำงานอยู่ แทนที่จะเป็นภาพที่ใช้การสร้างที่กำหนดไว้ใน DockerFile ซึ่งกล่าวถึงในส่วนก่อนหน้า
การกำหนดค่าการเขียนสำหรับโหมดการพัฒนานั้นคล้ายกับโหมดการปรับใช้มาก ความแตกต่างเพียงอย่างเดียวคือไม่มี server_container เนื่องจากเซิร์ฟเวอร์และไคลเอนต์เป็นอินสแตนซ์แยกต่างหากจาก Docker
.env.example เป็น .env และตั้งค่าของ ${DB_HOST} เป็น postgresclient/.env.production.example . ตัวอย่างเป็น client/.env.production${REACT_APP_GOOGLE_API} ใน client/.env.production ทำตามขั้นตอนเหล่านี้ Reverse Proxy จะต้องตั้งค่าเป็น Forward Access ไปยัง Jenkins และ Application Server พอร์ตที่ระบุใน ./env ต้องจับคู่กับพอร์ตใน Nginx Reverse Proxy Config
ก่อนอื่นให้ไปที่ไดเรกทอรีการกำหนดค่าไซต์ที่มีอยู่
cd /etc/nginx/sites-available/ สร้างไฟล์กำหนดค่า คุณสามารถตั้งชื่อได้ตามที่คุณทำ แนวปฏิบัติที่ดีคือการตั้งชื่อมันในลักษณะเดียวกับที่อยู่ DNS ของคุณ ในกรณีของเรามันคือ lora.fiit.stuba.sk
touch lora.fiit.stuba.sk คัดลอกและวางรหัสต่อไปนี้ไปยังไฟล์ที่สร้างขึ้นใหม่ เปลี่ยนการกำหนดค่าของ proxy_pass สำหรับแต่ละสถานที่ให้ตรงกับพอร์ตที่ระบุใน .env อย่าลืมปรับ server_name ให้ตรงกับ 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
}บันทึกไฟล์และรีสตาร์ทบริการ nginx
sudo systemctl restart nginx แอปพลิเคชันเจนกินส์ควรเข้าถึงได้ที่ lora.fiit.stuba.sk/jenkins ในกรณีของคุณมันจะเป็นชื่อ DNS ของคุณแทน lora.fiit.stuba.sk
เมื่อคุณต้องการเปลี่ยนบ้านเริ่มต้นสำหรับเจนกินส์คุณสามารถเปลี่ยนตัวแปร JENKINS_HOME คู่มือได้รับแรงบันดาลใจอย่างมากจากบทช่วยสอนนี้
สร้างไดเรกทอรีใหม่ที่คุณต้องการย้ายบ้านเจนกินส์ไป ในกรณีของเราคือ /data/jenkins
mkdir /data/jenkinsเปลี่ยนความเป็นเจ้าของของไดเรกทอรีที่สร้างขึ้นใหม่
sudo chown jenkins:jenkins /data/jenkins คัดลอกเนื้อหาจาก Old Jenkins Home Directory, /var/lib/jenkins/ , ไปยังไดเรกทอรีบ้าน Jenkins ใหม่, /data/jenkins/ โดยใช้คำสั่งต่อไปนี้
sudo cp -prv /var/lib/jenkins /data/jenkins/ถัดไปเปลี่ยนบ้านผู้ใช้เจนกินส์
sudo usermod -d /data/jenkins/ jenkins อัปเดตเส้นทางไดเรกทอรีโฮมไดเรกทอรีของเจนกินส์ใหม่ใน /etc/default/jenkins คุณสามารถใช้โปรแกรมแก้ไขใด ๆ ที่คุณเลือก ในกรณีของเราเราใช้ VI
sudo vi /etc/default/jenkinsเลื่อนลงไปที่ตำแหน่งบ้านของเจนกินส์และอัปเดตเส้นทางโฮมไดเร็กตอรี่ใหม่
# 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=trueเริ่มบริการ Jenkins โดยใช้คำสั่งต่อไปนี้
sudo service jenkins start
เยี่ยมชมเจนกินส์จากเบราว์เซอร์ของคุณที่ lora.fiit.stuba.sk/jenkins
เข้าสู่แอปพลิเคชัน
นำทางเพื่อ Manage Jenkins ที่อยู่ทางด้านซ้ายของหน้าจอ
คลิกที่แท็บ Manage Credentials ที่อยู่ใน Security group
จากนั้นคลิกที่ลิงค์ (global) ที่อยู่ในตาราง
คลิกที่ปุ่ม addCredentials ทางด้านซ้ายของหน้าจอ
เลือกตัวเลือก Secret file จากเมนู Kind เลื่อนลง
อัปโหลดไฟล์ .env ที่เติมเต็มและตั้งค่าฟิลด์ ID เป็น env
ทำซ้ำขั้นตอนที่ 6 จากนั้นอัปโหลดไฟล์ client/.env.production และตั้งค่าฟิลด์ ID เป็น envClient
สร้างข้อมูลรับรองอื่น แต่คราวนี้เลือก SSH Username with private key จากเมนูแบบเลื่อนลง ตั้งค่าฟิลด์ ID เป็น lora-application-server-ssh ในการรับคีย์ SSH สำหรับที่เก็บข้อมูลของคุณ (ที่ซอร์สโค้ดของแอปพลิเคชันเซิร์ฟเวอร์) ทำตามคำแนะนำนี้
จากแดชบอร์ดคลิกที่ปุ่ม New Item ซึ่งอยู่ทางด้านซ้ายของหน้าจอ
ป้อนชื่อที่ต้องการคลิกที่ปุ่ม Pipeline และยืนยันว่าคลิกที่ปุ่ม OK
ไปยังรหัส Pipeline Script Paste ต่อไปนี้
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 ( )
}
}บันทึกการเปลี่ยนแปลงและเรียกใช้ไปป์ไลน์แรกของคุณ
ยินดีด้วย! หลังจากที่ไปป์ไลน์ประสบความสำเร็จในการสร้างและปรับใช้แอปพลิเคชันแอปของคุณสามารถเข้าถึงได้ที่ lora.fiit.stuba.sk