As you can see from the previous article, I worked with different projects. The first days in a new team usually go the same way: the backender sits down to me and performs the magic steps to install and deploy the application. Docker is indispensable for front-end developers, because. The backend is often written in a wide range of PHP/Java/Python/C# stacks and the front doesn't need to distract the back each time to install and deploy everything. Only in one place I saw a bunch of Docker-Jenkins with a transparent deployment, logs, screwed with autotests.
A lot of detailed articles have been written about docker. This article will focus on deploying a Single Page Application using VueJS / Vue Router, the server part in the form of a RESTful API with NodeJS, and MongoDB is used as a database. Docker Compose is used to describe and run multiple container applications.
Why you need Docker
Docker allows you to automate the process of deploying an application. The developer no longer needs to install programs on his own, deal with version incompatibility on his machine. It is enough to install Docker and type 1-2 commands into the console. It is most convenient to do this on Linux.
Getting started
Set
Folder structure
We create 2 folders for client and server applications. A file with the .yml extension is a config Docker Composewhere the application containers are defined and linked.
docker-compose.yml:
version: "3"
services:
mongo:
container_name: mongo
hostname: mongo
image: mongo
ports:
- "27017:27017"
server:
build: server/
#command: node ./server.js #Π·Π΄Π΅ΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΠΈΡΠ°ΡΡ CMD ΠΈΠ· Dockerfile Π² /server
ports:
- "3000:3000"
links:
- mongo
client:
build: client/
#command: http-server ./dist #Π·Π΄Π΅ΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΠΈΡΠ°ΡΡ CMD ΠΈΠ· Dockerfile Π² /client
network_mode: host
ports:
- "8089:8089"
depends_on:
- server
We create 3 services in docker: for NodeJS, MongoDB and for statics on Vue. To connect client to server added depends on server. To link MongoDB with the server API, use links mongo. Server, client, mongo are the names of the services.
VueJS Client
In the folder /client the application is located on VueJS. Application created with
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"]
Note that package.json is copied and installed separately from the rest of the project files. This is done for performance so that the contents of the /node_modules folder are cached on rebuild. Each command line is cached separately.
At the end, when the container is started, the command is executed npm run dev
. This command is described in package.json:
"scripts": {
"test:dev": "http-server dist -p 8081 -c 1 --push-state"
}
To run files from a folder /dist, globally set http-server
, and in dev-dependencies package spa-http-server
to make Vue Router work correctly. The --push-state flag redirects to index.html. The -c flag with a value of 1 second has been added to http-server did not cache scripts. This is a test example, on a real project it is better to use nginx.
Create a field in the Vuex store apiHost: 'http://localhost:3000'
, where the NodeJS Api port is written. The client part is ready. Now all requests from the client to the back end go to this url.
NodeJS Server API
In the folder /server
create server.js and Dockerfile:
FROM node:10
WORKDIR /server
COPY ./package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Π server.js is indicated url for database const url = 'mongodb://mongo:27017/';
. We allow cross-domain requests from the client:
const clientUrl = 'http://localhost:8081';
const corsOptions = {
origin: clientUrl,
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 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));
});
Conclusion
Now go to the project directory and run docker-compose build
for imaging and docker-compose up
to run containers. The command will lift 3 containers: server, client, mongo. For a NodeJS server, you can configure hot-reload by linking it to the user folder. And the client is under development to run locally with hot reload, running separately server ΠΈ mongo. To start a separate service, just specify its name docker-compose up client
. Don't forget to do it sometimes prune
and removal of containers (containers), networks (networks) and images (images) to free up resources.
You can see the full code
Source: habr.com