前几天基于CentOS6.9的镜像安装无头浏览器Puppeteer,装上后问题很多,无法成功运行,装好这个依赖发现又缺少那个依赖,依赖全部装完后又提示版本不兼容。最终我还是选择放弃CentOS6,改为升级到CentOS7来构建Puppeteer的镜像。
构建Node+OpenResty的基础镜像 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 docker pull centos:7 docker run -tid centos:7 docker exec -ti xxxx /bin/bash# 创建安装目录 mkdir -p /tmp/install cd /tmp/install# 更换yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup curl "https://mirrors.aliyun.com/repo/Centos-7.repo" -o /etc/yum.repos.d/Centos-7.repo yum clean all yum makecache# 安装依赖库 yum install pcre-devel perl openssl-devel zlib-devel telnet wget which make -y# 安装并升级gcc和gcc-c++(Node 12.18.3 requires gcc and g++ >= 6.3 or newer) yum install gcc gcc-c++ -y yum install -y centos-release-scl yum install -y devtoolset-7-gcc devtoolset-7-gcc-c++ source /opt/rh/devtoolset-7/enable# 安装Node wget https://nodejs.org/dist/v12.18.3/node-v12.18.3.tar.gz tar -xvzf node-v12.18.3.tar.gz cd node-v12.18.3 ./configure --prefix=/usr/local/node make -j4 make install ln -s /usr/local/node/bin/node /usr/bin/node ln -s /usr/local/node/bin/npm /usr/bin/npm# 安装OpenResty cd /tmp/install wget https://openresty.org/download/openresty-1.17.8.2.tar.gz tar -xvzf openresty-1.17.8.2.tar.gz cd openresty-1.17.8.2 ./configure --prefix=/usr/local/openresty gmake gmake install useradd www# 设置时区(这个需要覆盖) cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime# 安装s6(TODO,没跑起来,是因为我少了ENTRYPOINT ["/init" ]) docker cp s6 695c769703a1:/tmp/install/ docker cp root 695c769703a1:/tmp/install/
制作专属Puppeteer的镜像 1 2 3 4 5 6 7 8 9 10 # 安装Chrome浏览器的依赖 # 依赖库 yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y# 字体 yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y# 全局安装Chrome浏览器 npm config set registry 'https://registry.npm.taobao.org' npm install -g puppeteer
遇到的问题 S6进程管理没有生效 这是因为我在构建镜像的Dockerfile中,缺少了这一行,没有启动S6进程:
sandbox Chrome推荐用户通过sandbox的模式,以非root用户运行程序:
https://chromium.googlesource.com/chromium/src/+/master/docs/linux/suid_sandbox_developm
然后我根据网上的教程配置sandbox:
https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#setting-up-chrome-linux-sandbox
1 2 3 4 5 6 cd /var/www/resource/server/node_modules/puppeteer/.local-chromium/linux-782078/chrome-linux/ chown root:root chrome_sandbox chmod 4755 chrome_sandbox cp -p chrome_sandbox /usr/local/sbin/chrome-devel-sandbox export CHROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox echo "export CHROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox" >> ~/.bashrc
配置后发现程序还是不能正常运行,后来找到网上的一个内容,说docker无解:
1 2 3 4 5 After researching extensively internet I think I found the answer: Sandboxing For security reasons, Google Chrome is unable to provide sandboxing when it is running in the container-based environment. To use Chrome in the container-based environment, pass the --no-sandbox flag to the chrome executable So it looks like there is no better solution than --no-sandbox for me, even though its not being very secure, there are people on the internet claiming that it is still safe to use "--no-sandbox" as its running within container which is extra protected any way.
因此最终还是在程序中设置不启用sandbox:
1 const browser = await puppeteer.launch ({args : ['--no-sandbox' , '--disable-setuid-sandbox' ]});
这样就可以正常运行了。也不用非root用户了,直接root也能跑起来。
docker启动后会自动退出 发现node程序没跑起来,排查过程又花了4个小时,最终发现是因为我解决文件编码问题的时候,是直接/bin/bash进入容器修改,然后commit生成新的镜像,导致新镜像里面带进去了/bin/bash,然后跑新镜像的时候,执行完内部脚本,就会执行/bin/bash,然后就退出了。
一定要通过Dockerfile来构建镜像,别手动修改,不然后续想部分重来,但是我又修改了中间的docker镜像,就不行了。