Așa cum am menționat în articolul anterior, am lucrat cu diferite proiecte. Primele zile într-o echipă nouă decurg de obicei la fel: backend developer se alătură echipei mele și efectuează acțiuni magice pentru instalarea și desfășurarea aplicației. Docker este esențial pentru frontend-eri, deoarece backend-ul este adesea scris într-o gamă largă de stack-uri PHP/Java/Python/C#, iar frontend-ul nu trebuie să deranjeze constant backend-ul pentru a instala și desfășura totul. Doar într-un singur loc am văzut o combinație Docker-Jenkins cu desfășurare transparentă, jurnale și teste automate integrate.
Despre Docker s-au scris multe articole detaliate. În acest articol, vom discuta despre desfășurarea unei aplicații de tip Single Page Application folosind VueJS/Vue Router, cu partea server ca un API RESTful c NodeJS, iar MongoDB utilizându-se ca bază de date. Pentru descrierea și lansarea mai multor aplicații-container se folosește Docker Compose.
De ce este necesar Docker
Docker permite automatizarea procesului de desfășurare a aplicației. Dezvoltatorul nu mai trebuie să instaleze programele manual, să se lupte cu incompatibilitatea versiunilor pe mașina sa. Este suficient să instaleze Docker și să ruleze 1-2 comenzi în consolă. Cel mai simplu este să facă acest lucru pe Linux.
Începuturi
Instalăm și
Structura folderelor
Creăm 2 foldere pentru aplicațiile client și server. Fișierul cu extensia .yml reprezintă configurația Docker Compose, unde container-urile aplicației sunt definite și legate.
Docker-compose.yml:
version: "3"
services:
mongo:
container_name: mongo
hostname: mongo
image: mongo
ports:
- "27017:27017"
server:
build: server/
#command: node ./server.js #aici se poate suprascrie CMD din Dockerfile în /server
ports:
- "3000:3000"
links:
- mongo
client:
build: client/
#command: http-server ./dist #aici se poate suprascrie CMD din Dockerfile în /client
network_mode: host
ports:
- "8089:8089"
depends_on:
- server
Creăm 3 servicii în Docker: pentru NodeJS, MongoDB și pentru statică pe Vue. Pentru a conecta clientul la server a fost adăugată depends on server. Pentru conectarea MongoDB cu API-ul serverului se folosește links mongo. Server, client, mongo - numele serviciilor.
Client pe VueJS
În folderul /client se află aplicația pe VueJS. Aplicația a fost creată cu ajutorul . La construirea imaginii, aplicația client este transformată într-un set de fișiere statice în folderul /dist. În Dockerfile este descris un set de comenzi pentru construirea imaginii:
FROM node:10
WORKDIR /client
COPY ./package*.json ./
RUN npm install
RUN npm install -g http-server
COPY . .
RUN npm run build
EXPOSE 8081
CMD ["npm", "test:dev"]
Rețineți că package.json este copiat și instalat separat de celelalte fișiere ale proiectului. Aceasta se face pentru performanță, astfel încât conținutul folderului /node_modules să fie stocat în cache la o recompunere ulterioară. Fiecare linie-comandă este stocată în cache separat.
La final, la lansarea containerului se execută comanda npm run dev. Această comandă este descrisă în package.json:
"scripts": {
"test:dev": "http-server dist -p 8081 -c 1 --push-state"
}
Pentru a rula fișierele din folderul /dist, se instalează global http-server, iar în dev-dependencies pachetul spa-http-server, pentru ca Vue Router să funcționeze corect. Flagra —push-state redirecționează către index.html. Flagra -c cu valoarea de 1 secundă a fost adăugată pentru a http-server nu caching scripturile. Acesta este un exemplu de testare, pentru un proiect real ar fi mai bine să folosești nginx.
În store-ul Vuex, creăm un câmp apiHost: 'http://localhost:3000', unde se specifică portul NodeJS Api. Partea client este gata. Acum toate cererile de la client către backend merg la acest url.
API-ul serverului NodeJS
În folderul /server creăm server.js și Dockerfile:
FROM node:10
WORKDIR /server
COPY ./package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
În server.js este specificat url pentru baza de date const url = 'mongodb://mongo:27017/';. Permitem cererile cross-origin de la client:
const clientUrl = 'http://localhost:8081';
const corsOptions = {
origin: clientUrl,
optionsSuccessStatus: 200, // unele browsere mai vechi (IE11, diverse SmartTV-uri) se blochează la 204
};
app.use(cors());
app.all('/*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', clientUrl);
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
app.get('/getProducts', cors(corsOptions), (req, res) => {
products.getContent
.then(data => res.json(data), err => res.json(err));
});
app.get('/getUsers', cors(corsOptions), (req, res) => {
db.getUsers()
.then(data => res.json(data), err => res.json(err));
});
Concluzie
Acum să trecem în directorul proiectului și să lansăm docker-compose build pentru a construi imaginile și docker-compose up pentru a lansa containerele. Comanda va ridica 3 containere: server, client, mongo. Pentru serverul pe NodeJS poți seta hot-reload, conectându-l cu folderul user. Iar clientul în stadiul de dezvoltare să fie lansat local cu hot reload, pornind separat server și mongo. Pentru a lansa un serviciu separat, este suficient să îi specifici numele docker-compose up client. Nu uita să faci din când în când prune și să ștergi containerele, rețelele (networks) și imaginile (images) pentru a elibera resursele.
Codul complet poate fi vizualizat . Proiectul este încă în stadiul de dezvoltare.
Sursa: habr.com
