0

I'm using docker-compose to build a buildroot repository, and want to mount the buildroot output directory as a volume, as it is quite useful for getting generated images without accesing the docker container.

This is my docker-compose.yml:

version: '3' 

services:
  db: 
    image: mycustom
    container_name: mucustom-container
    command: /bin/bash -c "clone-repo.sh && bash"
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
        ./output:/usr/local/share/broot/my-custom/output

The script clone-repo.sh is just used to clone the buildroot repository (included for reference):

#!/bin/bash
REPO=my-custom
BUILDROOT=/usr/local/share/broot/
# Create BUILDROOT
mkdir -p $BUILDROOT/$REPO
cd $BUILDROOT/$REPO
# Clone repo
if [ ! -d $BUILDROOT/$REPO/.git ]; then
    git init
    git remote add origin git@gitlab.com:my/platform/$REPO.git
    git pull origin master
    git fetch
fi

Using this version of docker-compose,

$ docker-compose --version
docker-compose version 1.29.1, build c34c88b2

the docker image builds as expected, and the build process of buildroot works fine.

However, I have migrated docker to this version:

$ docker --version
Docker version 20.10.5, build 55c4c88

Note for this particular version, "compose" is a functionality included inside the docker tool. Using this docker version, docker image is built as expected. However, the build process of buildroot fails:

*** Error during update of the configuration.
Makefile:999: recipe for target 'syncconfig' failed
make[1]: *** [syncconfig] Error 1

After analyzing buildroot source code, the problem is generated with the "rename" functions defined in this source file: support/kconfig/confdata.c

name = getenv("KCONFIG_AUTOHEADER");
if (!name)
    name = "include/generated/autoconf.h";
sprintf(buf, "%s.tmpconfig.h", dir);
if (rename(buf, name))
    return 1;
name = getenv("KCONFIG_TRISTATE");
if (!name)
    name = "include/config/tristate.conf";
sprintf(buf, "%s.tmpconfig_tristate", dir);
if (rename(buf, name))
    return 1;
name = conf_get_autoconfig_name();
sprintf(buf, "%s.tmpconfig", dir);
if (rename(buf, name))
    return 1;

All calls to rename return with 1. Analyzing the issue deeply, found this temporal files are generated fine:

a) /usr/local/share/broot/my-custom/.tmpconfig.h
b) /usr/local/share/broot/my-custom/.tmpconfig_tristate
c) /usr/local/share/broot/my-custom/.tmpconfig

But they can't be renamed to destination paths, located at output directory (remember, mounted as a volume):

a) /usr/local/share/broot/my-custom/output/build/buildroot-config/autoconf.h
b) /usr/local/share/broot/my-custom/output/build/buildroot-config/tristate.config
c) /usr/local/share/broot/my-custom/output/build/buildroot-config/auto.conf

What's different in the implementation between docker-compose tool (with hyppen) and docker compose (without hyppen)? Do you know why docker-compose allows this? And why docker compose is not supporting this?

aicastell
  • 2,182
  • 2
  • 21
  • 33

1 Answers1

1

The newer docker version uses a different type filesystem combining to mount the volume. As a result, /usr/local/share/broot/my-custom and /usr/local/share/broot/my-custom/output are now different filesystems, and it is not possible to rename() across filesystems.

As a workaround, either mount /usr/local/share/broot/my-custom as a volume, or use make O=... to use an out-of-tree build. In the latter case, the temporary files will be created in the specified output directory instead of in the buildroot directory. Note that for this to work, it must be mounted somewhere else than on /usr/local/share/broot/my-custom/output.

Arnout
  • 2,927
  • 16
  • 24