在 Vagrant 共享文件夹中安装 NPM 会导致文件系统问题

NPM install in Vagrant shared folder leads to filesystem issues

必须要有 Vagrant VM 才能拥有项目环境。在此 VM 中,Docker 存储库提供了使我的 API 工作正常运行所需的所有容器。在我安装正面 Angular 应用程序之前没有问题。

此应用正在使用 NPM、Bower、Gulp... 因此 CLI 容器实现了 NVM、NodeJS 和 NPM。容器成功构建,但是当我启动 npm install 时,我遇到了硬件问题。

我在模块安装期间得到的输出 告诉我:

gyp WARN install got an error, rolling back install
gyp ERR! configure error
gyp ERR! stack Error: EROFS: read-only file system, mkdir '/root/.node-gyp'
gyp ERR! stack     at Error (native)
gyp ERR! System Linux 4.4.0-59-generic
gyp ERR! command "/usr/local/nvm/versions/node/v6.9.5/bin/node" "/srv/apps/my-angular-app/node_modules/.bin/node-gyp" "rebuild"
gyp ERR! cwd /srv/apps/my-angular-app/node_modules/ttf2woff2
gyp ERR! node -v v6.9.5
gyp ERR! node-gyp -v v3.5.0
gyp ERR! not ok

PhantomJS not found on PATH
/tmp/phantomjs is not writable: EROFS: read-only file system, mkdir '/tmp/phantomjs'

npm install命令之后,Docker容器虚拟机文件系统被完全炸毁。无论我尝试做什么,我都会遇到文件系统错误。一个简单的 ls 输出如下:

bash: /bin/ls: Input/output error

当我尝试使用选项卡自动完成命令时:

-bash: cannot create temp file for here-document: Read-only file system

要使其再次运行,我必须重新启动 VM。

我的线索是 NPM 试图创建符号链接,这会导致系统因 Windows 而失败。事实上,该项目位于 Vagrant 共享文件夹中,我认为在这里创建符号链接是一件冒险的事情。但我不明白,因为我的 Nginx 容器做同样的事情(使用 sites-available/sites-enable/ 链接。我没有看到问题。我搜索了答案,但它似乎与诸如此类的问题无关

配置

Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :
require './config'
# Specify Vagrant version and Vagrant API version
Vagrant.require_version ">= 1.6.0"
VAGRANTFILE_API_VERSION = "2"

# Create and configure the VM(s)
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  # Forward the ports between the host machine and the box
  config.vm.network "forwarded_port", guest: 80, host: 80
  config.vm.network "forwarded_port", guest: 443, host: 443
  config.vm.network "forwarded_port", guest: 8000, host: 8000
  config.vm.network "forwarded_port", guest: 8082, host: 8082
  config.vm.network "forwarded_port", guest: 8888, host: 8888
  config.vm.network "forwarded_port", guest: 9000, host: 9000
  config.vm.network "forwarded_port", guest: 9001, host: 9001
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: VAGRANT_CONFIG['ip']

  # Assign a friendly name to this host VM
  config.vm.hostname = "docker-host"

  # Skip checking for an updated Vagrant box
  config.vm.box_check_update = false

  # SSH agent forwarding
  config.ssh.forward_agent = false

  # Spin up a "host box" for use with the Docker provider
  # and then provision it with Docker
  config.vm.box = "ubuntu/xenial64"
  config.vm.provision "docker"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"
  # argument is a set of non-required options.
  if VAGRANT_CONFIG['synced_folder'] == true
      if VAGRANT_CONFIG['nfs'] == true
        #config.nfs.map_uid = Process.uid
        #config.nfs.map_gid = Process.gid
        config.vm.synced_folder "share", "/home/ubuntu/data", type: 'nfs', nfs_udp: VAGRANT_CONFIG['nfs_udp']
      else
        config.vm.synced_folder "share", "/home/ubuntu/data"
      end
      #config.vm.synced_folder "www", "/home/vagrant/www", type: 'smb', smb_username: '', smb_password: '', mount_options: [""]
  end

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    # vb.gui = true

    # Customize the amount of memory on the VM:
    vb.memory = VAGRANT_CONFIG['memory']
    vb.cpus = VAGRANT_CONFIG['cpu']
    vb.name = "my-docker-vm"
  end

  config.vm.provider "vmware_fusion" do |v|
    v.vmx["memsize"] = VAGRANT_CONFIG['memory']
    v.vmx["numvcpus"] = VAGRANT_CONFIG['cpu']
    v.name = "my-docker-vm"
  end

  config.vm.provider "vmware_workstation" do |v|
    v.vmx["memsize"] = VAGRANT_CONFIG['memory']
    v.vmx["numvcpus"] = VAGRANT_CONFIG['cpu']
    v.name = "my-docker-vm"
  end

  config.vm.provision "file", source: "data", destination: "/home/ubuntu/install"

  config.vm.provision "shell", path: "scripts/install.sh"

  # Disable synced folders (prevents an NFS error on "vagrant up")
  config.vm.synced_folder ".", "/ubuntu", disabled: true
end

docker-compose.yml(CLI 容器)

cli:
    container_name: cli_container
    build: cli
    volumes:
        - "./volumes/apps:/srv/apps"
    stdin_open: true
    tty: true
    environment:
        - PHP_EXTRA_CONFIGURE_ARGS=--with-ldap
    links:
        - mysql:mysql
        - redis:redis
        - rabbitmq:rabbitmq
        - mailer:mailer
        - blackfire:blackfire

CLI 容器Docker文件

FROM php:cli

RUN rm /bin/sh && ln -s /bin/bash /bin/sh

COPY config/ssh/* /root/.ssh/
RUN chmod 600 /root/.ssh/id_rsa*

COPY config/php.ini /usr/local/etc/php/
COPY config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY config/symfony_environment.sh /usr/local/etc/symfony_environment.sh
COPY docker-entrypoint.sh /entrypoint.sh

RUN chmod a+x /entrypoint.sh && chown root:root /entrypoint.sh

RUN cat /usr/local/etc/symfony_environment.sh >> /etc/bash.bashrc

RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y wget git python-pip libmcrypt-dev libldb-dev libldap2-dev zlib1g-dev dos2unix build-essential libssl-dev
RUN dos2unix /entrypoint.sh
RUN apt-get --purge remove -y dos2unix
RUN rm -rf /var/lib/apt/lists/*

# nvm environment variables
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 6.9.5

# install nvm
# https://github.com/creationix/nvm#install-script
RUN curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash

# install node and npm
RUN source $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default

# add node and npm to path so the commands are available
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH

RUN npm install -g gulp bower

RUN pip install --upgrade pip
RUN pip install supervisor

RUN docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/
RUN docker-php-ext-install -j$(nproc) mcrypt zip bcmath ldap pdo pdo_mysql

RUN pecl install redis-3.1.0 && docker-php-ext-enable redis
RUN pecl install apcu-5.1.7 \
    && echo extension=apcu.so > /usr/local/etc/php/conf.d/apcu.ini

VOLUME /srv/apps
WORKDIR /srv/apps

ENTRYPOINT ["/entrypoint.sh"]

CMD ["/usr/local/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

我真的不明白是什么修复了它,但现在一切正常!

我认为这只是 NPM 的缓存问题。

事实上,当我在容器中安装 Node 堆栈时,我使用的是最新版本。然后,后来,我将其更改为采用 LTS 版本,并删除了容器以重新构建它。我认为这些问题来自 LTS 版本和最新版本缓存之间的冲突。

所以可能的解决方案是:

npm cache clean