CentOS+Docker+Mysql+Gerrit+Nginx configuration

Keywords: Nginx MySQL Java Docker

Software environment:

  • CentOS 7.0
  • Docker 18.06.0-ce

Following is the docker image

  • Mysql 5.7
  • Gerrit 2.15.3
  • Nginx 1.15.2-alpine

Assume that the current server ip address is (all three software are on the same server)

192.168.0.1

Note: When using docker image, it is strongly recommended to fix the mirror version number of the container instead of lastest.

This ensures that it works correctly in any environment, because different versions of mirrors may be configured differently. I have been in the pit for a long time.

Local directory structure (configuration directory containing mysql gerrit nginx 3 software):

├── docker-compose.yml
├── gerrit
│   └── review_site
├── mysql
│   └── db
└── nginx
    ├── logs
    └── nginx.conf


1. Configure docker-compose.yml file:

First configure Gerrit and Mysql, and then Nginx:

version: "3"
services:

  db:
    image: "mysql:5.7"
    ports:
      - "3306:3306"
    restart: always
    volumes:
      - /data/mysql/db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=XXXX

  gerrit:
    depends_on:
      - db
    image: "openfrontier/gerrit:2.15.3"
    ports:
      - "29418:29418"
      - "8080:8080"
    volumes:
      - /data/gerrit/review_site:/var/gerrit/review_site
    environment:
      - AUTH_TYPE=HTTP
      - WEBURL=http://192.168.0.1:8080
      - DATABASE_TYPE=mysql
      - DATABASE_HOSTNAME=db
      - DATABASE_PORT=3306
      - DATABASE_DATABASE=gerrit
      - DATABASE_USERNAME=gerrit
      - DATABASE_PASSWORD=gerrit

2. Start db database container first:

Priority must be given to starting the Mysql database here, because you need to create the gerrit database and operate the accounts of the gerrit database.

$ docker-compose up db

3. Configure the database:

After the database container is started, it enters the container with the root account:

$ docker-compose up db

Container names can be viewed through docker-compose ps

Enter mysql console with root account

root@d73a4491dba4:/# mysql -u root -p

Create gerrit database and set character set utf-8

mysql> CREATE database Database name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

Create gerrit account and password (name self-defined, mainly for gerrit database access) and set access permissions to gerrit database
Here, for testing purposes, I set up the database, account number and password as gerrit.

mysql> grant all privileges on gerrit.* to gerrit@'%' identified by 'gerrit';

Immediate refresh permission

mysql> flush privileges;

In the new version of mysql, the default value of timestamp needs to be configured manually. If the local test is not set, gerrit always makes errors when creating tables

Exception in thread "main" com.google.gwtorm.server.OrmException: Cannot apply SQL
CREATE TABLE account_group_members_audit (
added_by INT DEFAULT 0 NOT NULL,
removed_by INT,
removed_on TIMESTAMP NULL DEFAULT NULL,
account_id INT DEFAULT 0 NOT NULL,
group_id INT DEFAULT 0 NOT NULL,
added_on TIMESTAMP NOT NULL
,PRIMARY KEY(account_id,group_id,added_on)
)
    at com.google.gwtorm.jdbc.JdbcExecutor.execute(JdbcExecutor.java:44)
    at com.google.gwtorm.jdbc.JdbcSchema.createRelations(JdbcSchema.java:134)
    at com.google.gwtorm.jdbc.JdbcSchema.updateSchema(JdbcSchema.java:104)
    at com.google.gerrit.server.schema.SchemaCreator.create(SchemaCreator.java:81)
    at com.google.gerrit.server.schema.SchemaUpdater.update(SchemaUpdater.java:108)
    at com.google.gerrit.pgm.init.BaseInit$SiteRun.upgradeSchema(BaseInit.java:386)
    at com.google.gerrit.pgm.init.BaseInit.run(BaseInit.java:143)
    at com.google.gerrit.pgm.util.AbstractProgram.main(AbstractProgram.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.google.gerrit.launcher.GerritLauncher.invokeProgram(GerritLauncher.java:204)
    at com.google.gerrit.launcher.GerritLauncher.mainImpl(GerritLauncher.java:108)
    at com.google.gerrit.launcher.GerritLauncher.main(GerritLauncher.java:63)
    at Main.main(Main.java:24)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Invalid default value for 'added_on'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.Util.getInstance(Util.java:408)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2497)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2455)
    at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:839)
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:739)
    at com.google.gwtorm.jdbc.JdbcExecutor.execute(JdbcExecutor.java:42)
    ... 15 more

This can be solved by using MySQL root user login and setting global explicit_defaults_for_timestamp=1; as follows:

mysql> set global explicit_defaults_for_timestamp=1;

Database Configuration Completed, Exit

mysql> exit

4. You can start gerrit

$ docker-compose up gerrit

If the following words appear, the gerrit startup is successful

 [main] INFO  org.eclipse.jetty.server.Server : Started @22467ms
 [main] INFO  com.google.gerrit.pgm.Daemon : Gerrit Code Review 2.15.3 ready

5. Because we use HTTP authentication, we need to configure reverse proxy:

First, configure the docker-compose.yml file a nd modify the content under gerrit service:

Add environment variables: HTTPD_LISTEN URL = proxy-http:/*:8080/

Modify environment variables: WEBURL=http://192.168.0.1:8080 is WEBURL=http://192.168.0.1

That is to say, remove the port number.

As follows:

version: "3"
services:
  db:
    ...

  gerrit:
    ...
    environment:
      - AUTH_TYPE=HTTP
      - HTTPD_LISTENURL=proxy-http://*:8080/
      - WEBURL=http://192.168.0.1
    ...

b. Then prepare the nginx.conf file

This file is the configuration file of the Nginx server. You can get the default configuration file from the nginx container, and then modify it:

Here's how to do it from Nginx's official docker mirror website

$ docker run --name tmp-nginx-container -d nginx:1.15.2-alpine
$ docker cp tmp-nginx-container:/etc/nginx/nginx.conf /host/path/nginx.conf
$ docker rm -f tmp-nginx-container

The file/host/path/nginx.conf is a default configuration file that we can modify directly:

Add server (add start - --- add end) in the http section:

...
http {
    #add start
    server {
        listen *:80;
        server_name gerrit;
        location / {
            auth_basic "Restricted";
            auth_basic_user_file /etc/nginx/passwd;
            proxy_pass http://gerrit:8080/;
            proxy_set_header  X-Forwarded-For $remote_addr;
            proxy_set_header  Host $host;
        }
    }
    #add end
    ...
}
...

Explain several important points:

- server_name gerrit;
- proxy_pass http://gerrit:8080/;

Ser_name is generally used to specify the ip address or domain name, but here we use the docker container, and multiple containers run together, and the service name in docker-compose.yml is directly used for interconnection between containers, so gerrit is used here.

This is particularly important, I have been using the ip address before, gerrit has been unable to access the normal, drop pit for 2 days.

- auth_basic_user_file /etc/nginx/passwd;

Configure the authentication file for HTTP login, which saves the user account password and is created by the htpasswd command.
After the nginx.conf file is configured, it is placed in the local / data/nginx/nginx.conf, referring to the directory structure at the beginning of this article.

d. Create an authentication file passwd

$ htpasswd -c /data/gerrit/review_site/etc/passwd Full name

Enter your password after you return (the specific use of the htpasswd command can be Baidu itself).

e. Start the Nginx container

Add Nginx container configuration code in docker-compose.yml:

nginx:
    depends_on:
      - gerrit
    image: "nginx:1.15.2-alpine"
    ports:
      - "80:80"
    volumes:
      - /data/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /data/gerrit/review_site/etc/passwd:/etc/nginx/passwd

The passwd file here is created and saved locally by htpasswd and mounted in the Nginx container with volumes
Then you can start the Nginx container:

$ docker-compose up nginx

Or stop the Gerrit/Mysql container before you start the whole process:

$ docker-compose down
$ docker-compose up

If there are no errors in the startup process, the build is successful.
Client (another machine) accesses http://192.168.0.1
First, the Nginx server gets and pops up the input user name password window. After entering the account password (created by the htpasswd command above), it will be forwarded by Nginx to http://192.168.0.1:8080.

Finally, attach the complete configuration of docker-compose.yml nginx.conf (gerrit.config doesn't need to be modified independently, because when the container runs, it will be overwritten by environment variables in the docker-compose.yml file):

docker-compose.yml:

version: "3"
services:

  db:
    image: "mysql:5.7"
    ports:
      - "3306:3306"
    restart: always
    volumes:
      - /data/mysql/db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=XXX

  gerrit:
    depends_on:
      - db
    image: "openfrontier/gerrit:2.15.3"
    ports:
      - "29418:29418"
      - "8080:8080"
    volumes:
      - /data/gerrit/review_site:/var/gerrit/review_site
    environment:
      - AUTH_TYPE=HTTP
      - HTTPD_LISTENURL=proxy-http://*:8080/
      - WEBURL=http://192.168.0.1
      - DATABASE_TYPE=mysql
      - DATABASE_HOSTNAME=db
      - DATABASE_PORT=3306
      - DATABASE_DATABASE=gerrit
      - DATABASE_USERNAME=gerrit
      - DATABASE_PASSWORD=gerrit

  nginx:
    depends_on:
      - gerrit
    image: "nginx:1.15.2-alpine"
    ports:
      - "80:80"
    volumes:
      - /data/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /data/gerrit/review_site/etc/passwd:/etc/nginx/passwd

nginx.conf:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    #add start
    server {
        listen *:80;
        server_name gerrit;
        location / {
            auth_basic "Restricted";
            auth_basic_user_file /etc/nginx/passwd;
            proxy_pass http://gerrit:8080/;
            proxy_set_header  X-Forwarded-For $remote_addr;
            proxy_set_header  Host $host;
        }
    }
    #add end

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

The above involves account number, password, IP address, file path, please modify according to your actual situation.

 

Posted by voltrader on Fri, 21 Dec 2018 21:51:05 -0800