[Devops运维]如何用nginx部署一个bazel远程服务器

如何部署一个bazel远程服务器?

  • 常见的几种办法
    • 利用nginx部署远程缓存服务器
      • 1.制作一个nginx镜像(包含webdev)
        • 1.初始版本的dockerfile
        • 2.常见问题及解决办法
      • 2. nginx服务器设置
        • Q&A(常见问题与回答)
        • 将nginx服务器设置为缓存服务器需要进行的配置
      • 3.本地bazel构建的项目关联远程缓存服务器(bind)
        • Q:如何给本地项目绑定远程缓存服务器?
        • Q:怎么测试构建时启用了远程缓存呢?
        • Tip:
      • 4.项目实践
        • 前提条件
        • 测试环节

常见的几种办法

利用nginx部署远程缓存服务器

1.制作一个nginx镜像(包含webdev)

原因:nginx官方提供的nginx镜像是没有webdev模块的,没有办法进行远程缓存服务器的设置。所以需要我们自己制作一个包含webdev模块的nginx镜像。
思路:写一个dockerfile,基于Ubuntu的基础镜像制新的nginx镜像。

1.初始版本的dockerfile

ARG BASE="ubuntu:20.04"
FROM $BASE
COPY sources.list ./       #source.list文件里面是Ubuntu的软件源信息
RUN cp ./sources.list  /etc/apt/sources.list && \   #将软件源信息拷贝到ubuntu镜像里
    rm -rf ./sources.list
RUN apt-get update
RUN apt-get install -y vim
RUN apt-get install -y net-tools
RUN apt-get install -y nginx-extras
ENV MYPATH /usr/local
WORKDIR $MYPATH
EXPOSE 80
CMD echo "----- end -----"
CMD /bin/bash

Ubuntu 的软件源配置文件是 /etc/apt/sources.list

2.常见问题及解决办法

1.无法正常的进行apt -get update操作

原因:

  • 没有给Ubuntu镜像配置软件源,初始的Ubuntu镜像是什么都没有的
  • Dockerfile里的基础镜像Ubuntu版本和软件源的版本不一致,如From Ubuntu,默认基于最新的Ubuntu镜像,而软件源的设置是按其他版本的Ubuntu配置的,就可能无法正常update.

2.当我们执行docker build 生成镜像时debconf会问很多问题。
具体情况如下,会弹出很多question:

debconf: delaying package configuration, since apt-utils is not installed

Please select the geographic area in which you live. Subsequent configuration
questions will narrow this down by presenting a list of cities, representing
the time zones in which they are located.

  1. Africa      4. Australia  7. Atlantic  10. Pacific  13. Etc
  2. America     5. Arctic     8. Europe    11. SystemV
  3. Antarctica  6. Asia       9. Indian    12. US

解决办法:
参考文章:Avoid apt-utils warning in Debian Dockerfile

我们可以通过在Dockerfile中执行RUN时加上 export DEBIAN_FRONTEND=noninteractive
如:RUN export DEBIAN_FRONTEND=noninteractive && ...

修改完的Dockerfile如下:

ARG BASE="ubuntu:20.04"
FROM $BASE
COPY sources.list ./
RUN cp ./sources.list  /etc/apt/sources.list && \
    rm -rf ./sources.list
RUN apt-get update
RUN  DEBIAN_FRONTEND=noninteractive apt-get install -y vim
RUN  DEBIAN_FRONTEND=noninteractive apt-get install -y net-tools
RUN  DEBIAN_FRONTEND=noninteractive apt-get install -y nginx-extras
ENV MYPATH /usr/local
WORKDIR $MYPATH
EXPOSE 80
CMD echo "----- end -----"
CMD /bin/bash

但是此时的Dockerfile还是有问题,使用了太多的RUN指令,这样会产生很多的镜像层,使生成的镜像过于臃肿。所以我们可以将多个RUN指令进行合并,修改完的镜像如下:

ARG BASE="ubuntu:20.04"
FROM $BASE
ENV TZ=Asia/Shanghai \
    DEBIAN_FRONTEND=noninteractive
COPY sources.list  /etc/apt/sources.list
RUN apt-get update && \
    apt-get install -y nginx-extras && \
    apt-get clean
COPY nginx-bazel.conf /etc/nginx/sites-available/default #将本地写好的nginx配置文件直接复制到nginx镜像中
RUN mkdir -p /huge/www/html  /huge/www/cache /huge/client_temp \   #创建需要的缓存目录
    /huge/log/nginx /app/src && \
    chmod 777 /huge/www/cache
WORKDIR /app/src   #设置工作目录
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]  #容器启动时启动nginx服务

nginx-bazel.conf(服务器配置文件)

server {
        listen 80 default_server;

        root /huge/www;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name localhost;

        location /cache/ {
                root /huge/www;

                client_body_temp_path   /huge/client_temp;

                dav_methods PUT DELETE MKCOL COPY MOVE;
                dav_ext_methods PROPFIND OPTIONS;
                dav_access      user:rw group:rw all:rw;
                create_full_put_path    on;

                client_max_body_size 2G;
                fancyindex on;
                access_log /huge/log/nginx/access.log;
        }
}

相对于之前的镜像做出了以下改变

  • 将多条指令合并,使镜像更轻量
  • 使用apt安装软件后,清理软件—>apt-get clean
  • 去掉了不需要的环境变量,以免污染容器环境
  • 工作目录最好新建一个目录,因为容器运行时可能生成其他文件,如果在系统目录下会有不可预知的风险产生
  • 将服务器的配置文件从本地直接拷贝到镜像的/etc/nginx/sites-available/目录下,直接重命名为default,覆盖了nginx服务器的初始设置。(避免手动设置服务器配置)
  • 直接在镜像构建时就将服务器的缓存目录给创建好,不需要手动创建了。
  • 添加CMD指令容器启动后就可以直接启动nginx服务了,相当于容器启动了,nginx缓存服务器就可以直接运行了。

然后执行docker build,出现successfully就是成功了。

$ docker build -f Dockerfile -t bazel-cache-server:1.0 .
Sending build context to Docker daemon   5.12kB
Step 1/10 : ARG BASE="ubuntu:20.04"
Step 2/10 : FROM $BASE
 ---> 20fffa419e3a
Step 3/10 : ENV TZ=Asia/Shanghai     DEBIAN_FRONTEND=noninteractive
 ---> Using cache
 ---> ec3f9852ed64
Step 4/10 : COPY sources.list  /etc/apt/sources.list
 ---> d11f607b4fc6
Step 5/10 : RUN apt-get update &&     apt-get install -y nginx-extras &&     apt-get clean
 ---> Running in 25053684f808
Step 6/10 : COPY nginx-bazel.conf /etc/nginx/sites-available/default
 ---> 2e2eb9e7efc5
Step 7/10 : RUN mkdir -p /huge/www/html  /huge/www/cache /huge/client_temp     /huge/log/nginx /app/src &&     chmod 777 /huge/www/cache
 ---> Running in 85f986c8f2dd
Removing intermediate container 85f986c8f2dd
 ---> c5177bed8296
Step 8/10 : WORKDIR /app/src
 ---> Running in 75f09e7e95b1
Removing intermediate container 75f09e7e95b1
 ---> 69cfad7b9688
Step 9/10 : EXPOSE 80
 ---> Running in 4828bd9e565a
Removing intermediate container 4828bd9e565a
 ---> 2ec31ba86e3c
Step 10/10 : CMD ["nginx", "-g", "daemon off;"]
 ---> Running in 9c5fd100a93d
Removing intermediate container 9c5fd100a93d
 ---> 76847b7518d2
Successfully built 76847b7518d2
Successfully tagged bazel-cache-server:1.0
$ ls
Dockerfile  nginx-bazel.conf  sources.list

最后查看是否生成了镜像:docker images

REPOSITORY                                        TAG       IMAGE ID       CREATED         SIZE
bazel-cache-server                                1.0       76847b7518d2   3 minutes ago   226MB

2. nginx服务器设置

nginx镜像制作完毕之后,我们就可以根据镜像启动一个nginx容器实例,那么该容器就是提供远程缓存功能的nginx服务器。
需要注意的是:启动容器后并没有直接启动容器中的nginx服务,容器相当于一个微型的操作系统,所以得进入容器里手动启动一下nginx服务,或者在制作镜像dockerfile中写好启动nginx的指令。

Q&A(常见问题与回答)

Q:如何启动容器?
A:由于Dockerfile中指明容器暴露的端口是80端口,说明启动的nginx容器(微型操作系统)的可访问端口是80端口,那么我们要把它映射成虚拟机的某个可用端口,这样才能够访问到该服务。具体示例如下:
docker run --name mynginx -p 8089:80 -itd newnginx
说明:根据镜像newnginx启动一个新的容器实例,容器名字为mynginx,容器的80端口映射到虚拟机的8089端口。

Q:怎么进入容器内部?
A:docker exec -it mynginx bash ,mynginx是容器的名称

Q:如何在容器中启动nginx服务?
A:进入容器之后,首先用 ps aux | grep nginx查看nginx服务是否启动。结果如下:
说明还没有启动nginx

root@09497a291a10:/usr/local#  ps aux | grep nginx
root          22  0.0  0.0   3304   720 pts/1    S+   10:27   0:00 grep --color=auto nginx

所以现在找一下nginx的启动程序,输入find / -name nginx,结果如下:

root@09497a291a10:/usr/local# find / -name nginx
/var/log/nginx
/var/lib/nginx
/etc/init.d/nginx
/etc/logrotate.d/nginx
/etc/default/nginx
/etc/nginx
/etc/ufw/applications.d/nginx
/usr/share/nginx
/usr/sbin/nginx
/usr/lib/x86_64-linux-gnu/perl5/5.30/auto/nginx
/usr/lib/nginx

可以判断出/etc/init.d目录就是初始化nginx服务的位置,首先切换到该路径下,然后执行nginx程序。具体指令为cd /etc/init.d && nginx,执行结果如下。

root@09497a291a10:/etc/init.d# nginx
root@09497a291a10:/etc/init.d#  ps aux | grep nginx
root          26  0.0  0.0  97340  5172 ?        Ss   10:29   0:00 nginx: master process nginx
www-data      27  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
www-data      28  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
www-data      29  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
www-data      30  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
www-data      31  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
www-data      32  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
www-data      33  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
www-data      34  0.0  0.0  97692  6812 ?        S    10:29   0:00 nginx: worker process
root          36  0.0  0.0   3304   656 pts/1    S+   10:29   0:00 grep --color=auto nginx

Q:怎么测试nginx服务已经启动了?
A:两种方法:
一:在后台执行curl localhost:8089,如果有返回数据就是服务已经成功启动了。
二:在浏览器中输入网址:虚拟机IP地址:8089(端口号),如:http://10.128.128.152:8089/,浏览器如果成功返回welcome nginx的页面就是证明nginx服务正常。

Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

Q:怎么查看容器中nginx的日志?
A:用命令:tail -f /var/log/nginx/*.log,效果如下:

==> /var/log/nginx/error.log <==

==> /var/log/nginx/access.log <==
10.128.54.4 - - [16/Jun/2022:10:48:40 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
10.128.54.4 - - [16/Jun/2022:10:48:42 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"

将nginx服务器设置为缓存服务器需要进行的配置

准备操作:启动容器,进入容器内部,具体操作见上文。

  • docker run --name mynginx -p 8089:80 -itd newnginx 启动容器
  • docker ps 查看启动的服务
  • docker exec -it mynginx bash 进入容器
  • 进入容器后cd /etc/nginx

此时你可以看到如下的目录:

root@09497a291a10:/var/log/nginx# cd /etc/nginx
root@09497a291a10:/etc/nginx# ls
conf.d        fastcgi_params  koi-win     modules-available  nginx.conf    scgi_params      sites-enabled  uwsgi_params
fastcgi.conf  koi-utf         mime.types  modules-enabled    proxy_params  sites-available  snippets       win-utf

我们关注sites-available文件夹,该文件夹下有一个default文件,我们只要配置这个文件就可以。

root@09497a291a10:/etc/nginx# cd sites-available/
root@09497a291a10:/etc/nginx/sites-available# ls
default

编辑default文件,vi default
default文件:

server {
        listen 80 default_server;   #监听端口,即容器内nginx服务启动的端口
        listen [::]:80 default_server;


        root /huge/www;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name localhost;

        location /cache/ {
                root /huge/www;

                client_body_temp_path   /huge/client_temp;

                dav_methods PUT DELETE MKCOL COPY MOVE;
                dav_ext_methods PROPFIND OPTIONS;
                dav_access      user:rw group:rw all:rw;
                create_full_put_path    on;

                client_max_body_size 2G;
                fancyindex on;
                access_log /huge/log/nginx/access.log;
        }
}

然后我们将配置文件中的文件目录,在容器中进行创建。

mkdir -p /huge/www/html
mkdir -p /huge/www/cache  #缓存的文件主要就是存储在这里
mkdir -p /huge/client_temp
mkdir -p /huge/log/nginx

同时给文件夹/huge/www/cache设置写入权限,否则当本地构建的结果上传到nginx缓存服务器时,会出现Permission denied权限不够的错误,无法写入。

chmod 777 /huge/www/cache
root@09497a291a10:/huge/www# ls -ll
total 8
drwxr-xr-x 2 root root 4096 Jun 16 11:20 cache
drwxr-xr-x 2 root root 4096 Jun 16 11:20 html
root@09497a291a10:/huge/www# chmod 777 cache
root@09497a291a10:/huge/www# ls -ll
total 8
drwxrwxrwx 2 root root 4096 Jun 16 11:20 cache
drwxr-xr-x 2 root root 4096 Jun 16 11:20 html
root@09497a291a10:/huge/www#

好了到这里服务器的配置已经成功设置好了,停止容器重启容器后,就可以了。现在只需要把本地用bazel构建的项目和远程的nginx缓存服务器进行关联即可。

  • exit退出容器
  • docker stop mynginx 停止容器
  • docker start mynginx 启动容器

3.本地bazel构建的项目关联远程缓存服务器(bind)

前提条件:假设你已经具有成功用bazel构建项目的所有条件

  • 本地有一个bazel项目
  • 安装了bazel依赖sudo apt install g++ unzip zip python3
  • 安装了bazel

Q:如何给本地项目绑定远程缓存服务器?

A:bazel的工作空间中有一个.bazelrc文件,我们关注该文件,编辑该文件,添加以下信息
.bazelrc文件:

build --remote_cache=http://localhost:8089/cache
#上面的地址就是缓存服务器的地址,根据你的服务器设置进行修改。

Q:怎么测试构建时启用了远程缓存呢?

A:主要测试有远程缓存和没有远程缓存的情况,具体操作如下:

  • 在.bazelrc文件中设置远程缓存服务器地址,然后构建项目,可以看到构建结果上传到缓存服务器。
$ make bazel-build   ##用mak对项目进行了简单的管理
INFO: Invocation ID: 3de47f29-51e3-43a6-ac4c-5b0acb998831
 ===> Building tiger-controller with Bazel <===
bazel build //cmd/tiger-controller:tiger-controller
INFO: Invocation ID: b5c13628-c91e-4ea4-8927-6fab62bf40df
INFO: Analyzed target //cmd/tiger-controller:tiger-controller (447 packages loaded, 11733 targets configured).
INFO: Found 1 target...
Target //cmd/tiger-controller:tiger-controller up-to-date:
  bazel-bin/cmd/tiger-controller/tiger-controller_/tiger-controller
INFO: Elapsed time: 4.463s, Critical Path: 1.71s
INFO: 400 processes: 396 remote cache hit, 4 internal.===>表示有396个缓存命中
INFO: Build completed successfully, 400 total actions

nginx缓存服务器中:

root@5a92a4a5e992:/huge/www/cache# ls -lh
total 240K
drwxrwxrwx 2 www-data www-data  52K Jun 16 14:32 ac
drwxrwxrwx 2 www-data www-data 180K Jun 16 14:32 cas
  • 接着清理构建结果,clean清理之后,在.bazelrc文件中注释掉指定远程缓存服务器的信息,再次构建项目。
INFO: Analyzed target //cmd/tiger-controller:tiger-controller (447 packages loaded, 11733 targets configured).
INFO: Found 1 target...
Target //cmd/tiger-controller:tiger-controller up-to-date:
  bazel-bin/cmd/tiger-controller/tiger-controller_/tiger-controller
INFO: Elapsed time: 29.083s, Critical Path: 21.15s===>构建时间明显变长了
INFO: 400 processes: 4 internal, 396 linux-sandbox.
INFO: Build completed successfully, 400 total actions

Tip:

远程缓存的作用:bazel第一次构建项目的时候,会将构建结果(二进制文件)上传到远程缓存服务器(nginx)上,构建结束后,你清理一下本地缓存,执行bazel clean操作,然后再构建项目,执行bazel build,就可以明显看到bazel直接从缓存服务器上拉取之前的构建结果,大大提升了构建速度。(构建的结果是以哈希值进行区分的)
本地构建到一半终止后,再次启用远程缓存构建时,会直接从缓存服务器中获得剩下的构建结果。

4.项目实践

现在nginx缓存服务器也搭好了,我们通过一个构建一个简单的cpp项目进行测试。

前提条件

  • 从 Bazel 的 GitHub 代码库检索示例项目,clone到本地:
    git clone https://github.com/bazelbuild/examples
  • 以容器方式启动的nginx缓存服务器地址:localhost:8089
  • 构建的示例项目和nginx服务都在一台虚拟机上(可以在不同机器,只要可以互相访问即可)

测试环节

在样例程序中找到examples/cpp-tutorial/stage2,然后新建一个.bazelrc文件,在文件中指明缓存服务器的地址:vi .bazelrc
.bazelrc文件

build --remote_cache=http://localhost:8089/cache

然后构建hello-world项目

➜ stage2 bazel build //main:hello-world  #将构建结果上传到缓存服务器中
INFO: Invocation ID: cb5b365a-24b7-45cf-b677-d84d8ed0da45
INFO: Analyzed target //main:hello-world (37 packages loaded, 164 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 1.087s, Critical Path: 0.53s #无缓存的构建速度
INFO: 7 processes: 4 internal, 3 linux-sandbox.
INFO: Build completed successfully, 7 total actions
➜ stage2 bazel clean  #清理本地缓存
INFO: Invocation ID: 59a88152-76de-4cee-873a-11da4ca03200
INFO: Starting clean (this may take a while). Consider using --async if the clean takes more than several minutes.
➜ stage2 bazel build //main:hello-world  #再次构建,会从服务器拉取已有的构建结果
INFO: Invocation ID: 8252066f-f572-46e1-933c-94952c6ed439
INFO: Analyzed target //main:hello-world (37 packages loaded, 164 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 0.492s, Critical Path: 0.03s #有缓存的构建速度
INFO: 7 processes: 3 remote cache hit, 4 internal.
INFO: Build completed successfully, 7 total actions

查看缓存服务器多了什么:

root@5a92a4a5e992:/huge/www/cache/cas# ls
0bfdc46886dacdb41269ae2ac22cd4f9ada203a37ea7fd9b260d2f2e96dd8fa6  9903ed97a739fda63c5731c3fa01a22a902763060ca7ed11cd2ab2462b08adee
......
root@5a92a4a5e992:/huge/www/cache/cas# cd ../ac
root@5a92a4a5e992:/huge/www/cache/ac# ls
96c5d143551dea69e8b2f418a22d66fb56d845933581dfe35f6d0180ca064ee9  e28750895c1576be99687f4379581f4f234c98f8a100dc616efeb8d20c6a3bce
e02146d8850739017fe973e8fd2c769e7543bf48f9fd17b5ae0a7df5ede58b65

注:

Bazel 支持通过 HTTP/1.1 进行远程缓存。该协议在概念上很简单:二进制数据 (BLOB) 通过 PUT 请求上传,并通过 GET 请求下载。操作结果元数据存储在路径 /ac/ 下,输出文件存储在路径 /cas/ 下。

你可能感兴趣的:(DevOps,Linux学习笔记,服务器,运维,devops)