One, foreword

We often see a lot of good open source projects, but it can be complicated to install and run locally, configure different environments, install different dependencies, better docker pull directly, or package.

All of these will undoubtedly increase the cost of beginners, so this article summarizes one of the commonly used solutions at present:

Using Docker-compose to manage multiple services simultaneously requires only one commanddocker compose up -d, you can start a complete service that includes back-end projects, front-end projects, and databases.

Docker-compose, as an orchestration tool for docker containers, can help us manage multiple Docker containers.

In fact, the overall process is not difficult, but to complete the configuration, but also a lot of steps, this article is mainly from the perspective of actual combat, the whole process together. Nginx, Docker, docker-compose, node, mysql also need to know.

Suitable for reading:

  • Basic understanding of Docker
  • Multiple projects need to be deployed simultaneously
  • A full deployment of open source projects or self-built projects is required
  • You need to package and deploy an entire website

Need to prepare in advance:

  • Docker installed and started (demo version below)

  • Docker-compose (docker installation will automatically install at the same time, if not can install, also very easy)
  • A front-end project (demonstrated here using the React SPA)
  • A back-end project (Express here)

As shown, different containers can be started at once with the Docker-Componse.yml file, and then they can all be serviced externally.

Second, front-end project construction

1. Front-end project handling

First, we download a project template through CRA. In order to simulate the actual project needs, we do some processing on the downloaded template so that the project can be

  • 1. Distinguish whether the current project is in a pre-release or production environment
  • 2. Introduce Axios to request interfaces

Next we package YARN Build :prod, and the packaged folder build is the static resource we want to deploy.

Relevant content has been mentioned in the previous engineering practice. If you have any questions, please refer to it

  • Front End Engineering Practice – Configure the Pre-release environment and production Environment for React Projects (PART 3)

2. Pull Nginx image deployment

We deploy the previously packaged static resources through Docker

The path of the current project is/Users/user/Desktop/mine/fronted demo2 / build

Run the following command line directly to start the front-end service

docker run -d -p 80:80 -v /Users/user/Desktop/mine/fronted-demo2/build:/usr/share/nginx/html --name frontend-test nginx
Copy the code

The current service is in the production environment. Because the back-end service is not deployed, the database data is empty.

Testing, we switch the route and find that the page 404 is because the single-page application route is in the front and needs to be forwarded by Nginx. Then we override the configuration in the container with the nginx configuration in the project

Extract the Nginx configuration into the project

First, let’s go to the Docker container from the previous step and see the path to Nginx.

docker exec -it frontend-test /bin/bash
Copy the code

Create nginx/default.conf in the root directory of the project

server {
    listen  80;
    server_name  localhost;
    underscores_in_headers  on;
    root /home/frontend;
    location / {
      try_files $uri $uri/ @router;
      index index.html;
    }
    location @router {
      rewrite^. * $ /index.html last; }}Copy the code

Then start the container by mounting it and find that the access is normal.

4, write Dockerfile file

FROM nginx

WORKDIR /home/frontend

COPY build .

COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf

EXPOSE 80
Copy the code

In the project root directory, create a new Dockerfile file, including the base image, the working directory, copy the project to the image, and copy the Nginx configuration file to the image.

5. Build the front-end service image and start it

docker build -t frontend .

docker images

docker run -d -p 80:80 --name frontend-v1 frontend
Copy the code

You can find that the mirror of the front-end service has been packaged and started, enable local port 80 access, and delete the mirror frontend after the test is complete. You can also push the image to the mirror warehouse, or pull it directly from the remote.

If the Docker container is not deleted, you need to change the name of the restart container.

3. Database startup

1. Pull and start the database and connect to the database

docker run -p 3306:3306 --restart=always --privileged=true --name mysql -v /Users/user/Desktop/mysql/data:/var/lib/mysql  -v /Users/user/Desktop/mysql/my.cnf:/etc/mysql/my.cnf -e MYSQL_ROOT_PASSWORD="123456" -d mariadbCopy the code

Mariadb is selected here because my M1 computer does not support mysql mirroring, so I changed it to Mariadb, using the same. In addition to starting the database service, the command above also sets some configuration of the data, password, database data locally.

[mysqld] skip-name-resolve user=root character-set-server=utf8 default_authentication_plugin=mysql_native_password sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION [client] default-character-set=utf8 [mysql] default-character-set=utf8Copy the code

2. Create a new library and table

Here you can go into the container to manipulate the database, and you can also use the client to connect to the database

4. Start the back-end project

1. Download the Express project template and connect the database

Here configure the database, write the project interface, ensure that the local startup service is normal.

2. Pull up the image and deploy the image

We chose to use PM2 to deploy the service. In order to distinguish the production environment from the pre-release environment, we created a new pm2.config.js in the root directory, and then started the corresponding environment by passing different parameters

module.exports = {
  apps : [
      {
        name: "myapp",
        script: "./bin/www",
        watch: true,
        env: {
            "NODE_ENV": "development"
        },
        env_production: {
            "NODE_ENV": "production",
        }
      }
  ]
}
Copy the code

Pm2 start pm2.config.js –env development

Pm2 start pm2.config.js –env production

Read from process.env.node_env in the project

Write a Dockerfile and build a new image

FROM keymetrics/pm2

RUN mkdir -p /home/backend

WORKDIR /home/backend

COPY ./ /home/backend

RUN yarn install

ENV NPM_CONFIG_LOGLEVEL warn

EXPOSE 9000

CMD ["pm2-runtime", "start", "pm2.config.js", "--env", "production"]
Copy the code

Then build an image docker build-t backend.

Docker-comemess. yml configuration

Up to now, we have three Docker images, which are front-end service images, back-end service images and database images. We then write docker-comemage. yml to start all three services simultaneously and in the same order

Docker-compose compose configuration file

Create a new directory, then create docker-comemage. yml and mysql, mysql contains mysql data and log information, so that you do not need to restart the service to cause database information loss

version: '3'

networks:
  app-web:
   driver: bridge

services:
  mysql:
    image: mariadb
    ports:
     - 3306:3306
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    networks:
     - app-web
    environment:
     - TZ=Asia/Shanghai
     - MYSQL_USER=root
     - MYSQL_ROOT_PASSWORD=123456
    volumes:
     - ./mysql/data:/var/lib/mysql
     - ./mysql/my.cnf:/etc/mysql/my.cnf
     - /etc/localtime:/etc/localtime
  backend:
    image: backend
    ports:
     - 9000:9000
    depends_on:
     - mysql
    networks:
     - app-web
  frontend:
    image: frontend
    ports:
     - 80:80
    depends_on:
     - backend
Copy the code

The entire configuration file is a complete project, including mysql, Backend and frontend. Each part is similar to the configuration of Dockerfile. Depends_on has been added. Networks allows different containers to run on the same network.

Of course, this only provides the most basic configuration, more complex configuration needs to be refined according to the usage scenario.

2. Start the service

docker compose up -d
Copy the code

-d is run in the way of daemon. You can view all the current running services through Docker PS.

docker compose down
Copy the code

This statement will stop all services under the current cluster and delete the container.

Up to now, our docker-compose overall package deployment of a website has been completed, there may be a variety of pits in the process, but as long as the configuration error log query, you can solve one by one.

If you need to redeploy one, or release a new version, you can simply update docker-comemage.yml

Six, pay attention

1, mysql configuration

Some of the database and project information needs to be flexibly configured according to your needs.

2, automatic database migration

We found that some new database tables were not initialized, resulting in manual processing. In the project, we could use scripts or use some database encapsulated ORM for automatic migration.

3. Some error messages are reported

Mysql > set host to mysql

  • 1. If the docker pull mirror is slow, domestic mirror can be considered
  • 2. Front-end and back-end projects can use any language, as long as they have different mirrors.

Docker View logs

docker logs -f --tail 100 containerId

Vii. Reference materials

  • PM2 website
  • docker-compose
  • Express