Docker Swarm部署报错:绑定路径不存在,疑似自动绑定docker子目录
Docker Swarm部署报错:bind path is not exist
我在Docker Swarm部署服务时碰到bind path is not exist错误,发现Docker试图绑定根目录下docker目录的所有子目录,但我没在Compose文件或GitLab CI配置里声明过相关绑定规则。已经排查过引入的CI文件只处理PHP相关构建,没涉及Docker或环境变量,甚至移除了include配置,问题还是没解决。
文件结构
docker/ deploy/ service.yml volume/ redis/.gitkeep logs/.gitkeep
GitLab CI配置(.gitlab-ci.yml)
# 已确认引入的文件仅处理PHP相关构建,未涉及Docker或环境变量 include: - project: project/repository file: "deploy/php-ci.yml" stages: - build - test - release variables: IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA PROJECT_CODE: "service-2" PROJECT_NAMESPACE: "service-2" cache: paths: - vendor/ - node_modules/ branch-build: rules: - if: $CI_COMMIT_BRANCH == 'stage' when: always - if: $CI_COMMIT_BRANCH == 'main' when: always - if: $CI_PIPELINE_SOURCE == 'merge_request_event' when: always - if: $CI_COMMIT_BRANCH == 'devops' when: always unit-test: stage: test image: $IMAGE allow_failure: false needs: - branch-build variables: ELASTIC_HOST: "elasticsearch.logs:9300" ELASTIC_LOGS_INDEX: "test_service_api" before_script: - COMPOSER_ALLOW_SUPERUSER=1 composer install --dev --no-interaction - cp .env.example .env - php artisan key:generate script: - php artisan test rules: - if: $CI_COMMIT_BRANCH == 'main' when: always - if: $CI_COMMIT_BRANCH == 'stage' when: always - if: $CI_PIPELINE_SOURCE == 'merge_request_event' when: always - if: $CI_COMMIT_BRANCH == 'devops' when: always prod-deploy: needs: - branch-build - unit-test rules: - if: $CI_COMMIT_BRANCH == 'main' when: always stage-deploy: needs: - branch-build - unit-test rules: - if: $CI_COMMIT_BRANCH == 'stage' when: always # 自定义部署任务 devops-deploy: stage: release environment: staging needs: - branch-build - unit-test before_script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - cp $ENV_STAGING ./docker/deploy/.env - cat ./docker/deploy/.env script: - docker stack deploy -c ./docker/deploy/wizard.yml --with-registry-auth wizard tags: - swarm-stage rules: - if: $CI_COMMIT_BRANCH == 'devops' when: always
Compose配置(service.yml)
version: "3.8" services: app: image: ${IMAGE} deploy: replicas: 1 restart_policy: condition: any delay: 1s update_config: failure_action: rollback parallelism: 1 delay: 10s networks: - proxy_main - apiats-swarm-internal ports: - "8090:80" working_dir: /var/www/html env_file: - .env volumes: # 仅声明了以下绑定,未涉及deploy目录 - ./:/var/www/html - ./docker/volumes/logs:/var/logs labels: - "traefik.enable=true" - "traefik.http.routers.wizard-api-app.rule=Host(`service.local`)" - "traefik.http.routers.wizard-api-app.entrypoints=web" mailhog: image: mailhog/mailhog:latest deploy: replicas: 1 restart_policy: condition: any delay: 1s update_config: failure_action: rollback parallelism: 1 delay: 10s ports: - "8025" networks: - swarm-internal networks: proxy_main: external: true swarm-internal: external: true
Dockerfile
FROM php:8.2.15-apache RUN apt-get update && apt-get install -y \ curl \ libpng-dev \ libonig-dev \ libxml2-dev \ zip \ unzip \ supervisor \ zlib1g-dev ENV APACHE_DOCUMENT_ROOT=/var/www/html/public RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf RUN sed -ri -e 's!/var/www!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf RUN a2enmod rewrite headers RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd opcache iconv RUN unlink /etc/localtime RUN ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime ENV LOG_CHANNEL=stderr RUN apt-get clean && rm -rf /var/lib/apt/lists/* RUN pecl install redis && docker-php-ext-enable redis COPY --from=composer:latest /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html COPY *.json *.lock ./ COPY . . COPY ./docker-entrypoint.sh /docker-entrypoint.sh COPY ./.build/supervisor.conf /etc/supervisor/conf.d/ss.conf RUN cp "/var/www/html/.build/php.ini" "$PHP_INI_DIR/php.ini" RUN composer check-platform-reqs \ && COMPOSER_ALLOW_SUPERUSER=1 composer install \ --no-dev \ --prefer-dist \ --no-scripts \ --optimize-autoloader \ --no-interaction \ && composer clear-cache RUN chmod +x /docker-entrypoint.sh ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["apache2-foreground"]
排查与解决建议
- 核对部署用的Compose文件:CI脚本里部署的是
wizard.yml,但你提供的是service.yml,确认这两个文件内容是否一致。如果wizard.yml里存在错误的volume绑定规则,会直接导致路径不存在的问题。 - 替换相对路径为绝对路径:Swarm模式下,volume的相对路径是基于Swarm节点的工作目录,而非GitLab Runner的工作目录。把
volumes里的相对路径改成节点上的绝对路径,比如/opt/service-2/docker/volumes/logs:/var/logs,同时提前在节点上创建该目录。 - 检查Swarm节点的目录状态:直接登录
swarm-stage标签的节点,查看根目录下的docker目录是否存在,以及docker/volumes/logs等路径是否创建。如果路径不存在,手动创建后再部署。 - 排查.env文件内容:你将
$ENV_STAGING复制到部署目录的.env,检查这个文件里是否有和volume相关的变量,比如是否存在被Compose引用的VOLUME_*变量,导致意外的路径绑定。 - 移除不必要的目录绑定:
app服务里绑定./:/var/www/html在Swarm模式下风险极高,因为每个节点的本地目录结构不同,会覆盖容器内的代码。既然代码已经打包进镜像,直接删除这个volume绑定即可。
内容的提问来源于stack exchange,提问作者ChannelDSR
相关产品推荐
相关产品推荐

