{"id":18586084,"url":"https://github.com/savoirfairelinux/cqfd","last_synced_at":"2026-01-17T12:33:49.317Z","repository":{"id":8408380,"uuid":"58283472","full_name":"savoirfairelinux/cqfd","owner":"savoirfairelinux","description":"cqfd helps running commands inside the Docker container configured for your project, keeping the user and working directory the same inside the container","archived":false,"fork":false,"pushed_at":"2025-03-28T18:07:09.000Z","size":356,"stargazers_count":68,"open_issues_count":20,"forks_count":31,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-03-28T18:28:14.063Z","etag":null,"topics":["artifacts","configuration-management","developer-tools","development-environment","docker-container"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/savoirfairelinux.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-07T20:36:05.000Z","updated_at":"2025-03-25T15:29:12.000Z","dependencies_parsed_at":"2023-01-11T17:23:14.240Z","dependency_job_id":"e685ba3f-12b6-440f-a290-12e291228b07","html_url":"https://github.com/savoirfairelinux/cqfd","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savoirfairelinux%2Fcqfd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savoirfairelinux%2Fcqfd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savoirfairelinux%2Fcqfd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/savoirfairelinux%2Fcqfd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/savoirfairelinux","download_url":"https://codeload.github.com/savoirfairelinux/cqfd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399877,"owners_count":20932876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["artifacts","configuration-management","developer-tools","development-environment","docker-container"],"created_at":"2024-11-07T00:36:33.628Z","updated_at":"2026-01-17T12:33:49.305Z","avatar_url":"https://github.com/savoirfairelinux.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"![cqfd logo](./doc/cqfd_logo.png?raw=true)\n\n# What is cqfd?\n\ncqfd provides a quick and convenient way to run commands in the current\ndirectory within a Docker container defined by a per-project configuration\nfile.\n\nThis becomes useful when building an application designed for another\nLinux system, e.g. building an old embedded firmware that only works\nin an older Linux distribution.\n\n# Using cqfd\n\n## Getting started\n\nFollow these steps:\n\n* Ensure the [requirements](#requirements) are met\n* [Install cqfd](#installingremoving-cqfd)\n* Go to your project's directory\n* Create a `.cqfdrc` file\n* Create a Dockerfile and save it as `.cqfd/docker/Dockerfile`\n* Run `cqfd init`\n\nExamples are available in the `samples/` directory.\n\n`cqfd` will use the provided Dockerfile to create a normalized runtime\nbuild environment for your project.\n\n## Using cqfd on a daily basis\n\n### Regular builds\n\nTo build your project from the configured build environment with the\ndefault build command as configured in `.cqfdrc`, use:\n\n    $ cqfd\n\nAlternatively, you may want to specify a custom command to be\nexecuted from inside the build container.\n\n    $ cqfd run make clean\n    $ cqfd run \"make linux-dirclean \u0026\u0026 make foobar-dirclean\"\n\nThe `run` command is broken in some situations, and it is then recommended to\nuse `exec` for a single command, `shell -c` for a command composed with shell\ngrammar, or `shell` to run a shell script with or without arguments:\n\n    $ cqfd exec make clean\n    $ cqfd shell -c \"make linux-dirclean \u0026\u0026 make foobar-dirclean\"\n    $ cqfd shell ./build.sh debug\n\nWhen `cqfd` is running, the current directory is mounted by Docker\nas a volume. As a result, all the build artefacts generated inside the\ncontainer are still accessible in this directory after the container\nhas been stopped and removed.\n\n### Release\n\nThe `release` command behaves exactly like `run`, but creates a release\ntarball for your project additionally. The release files (as specified\nin your `.cqfdrc`) will be included inside the release archive.\n\n    $ cqfd release\n\nThe resulting release file is then called according to the archive\ntemplate, which defaults to `%Po-%Pn.tar.xz`.\n\n### Flavors\n\nFlavors are used to create alternate build scenarios. For example, to\nuse another container or another build command.\n\n## The .cqfdrc file\n\nThe `.cqfdrc` file at the root of your project contains the information\nrequired to support project tooling. It is written in an .ini-like\nformat and `samples/dot-cqfdrc` is an example.\n\nHere is a sample `.cqfdrc` file:\n\n    [project]\n    org='fooinc'\n    name='buildroot'\n\n    [build]\n    command='make foobar_defconfig \u0026\u0026 make \u0026\u0026 asciidoc README.FOOINC'\n    files='README.FOOINC output/images/sdcard.img'\n    archive='cqfd-%Gh.tar.xz'\n\n### Comments\n\nThe `.cqfdrc` file supports Unix shell comments; the words after the character `#`\nare ignored up to the end of line. A comment cannot be set in the first line,\nand right after a section.\n\n### The [project] section\n\n`org`: a short, lowercase name for the project’s parent organization.\n\n`name`: a short, lowercase name for the project.\n\n`build_context` (optional): a directory to pass as the build context\nto Docker. This should be specified relatively to where `cqfd` is\ninvoked.  For example, it can be set to `.`, to use the current\nworking directory of the invoked `cqfd` command as the Docker build\ncontext, which can be useful when files at the root of the project are\nrequired to build the image.  When using this option, a\n`.dockerignore` file can be useful to limit what gets sent to the\nDocker daemon.\n\n`custom_img_name` (optional): allows specifying a custom Docker image name\ninstead of the one automatically generated by cqfd. You can also include a\nprivate repository URL in the image name. If you do, cqfd will try to pull the\nimage from the provided repository, if not already available on your system.\n\n#### Docker image naming\n\nUnless `custom_img_name` is used, Docker images generated by cqfd will be\nnamed `cqfd_$username_$org_$name_$hash`, using the following variables:\n\n* `$username`: The UNIX username used to launch cqfd.\n* `$org`: The `org` variable in the `[project]` section of your `.cqfdrc`.\n* `$name`: The `name` variable in the `[project]` section of your `.cqfdrc`.\n* `$hash`: A hash of the local Dockerfile.\n\n### The [build] section\n\n#### `cqfd run`\n\n`command`: the command string to be executed when cqfd is invoked. This\nstring will be passed as an argument to a classical `sh -c \"commands\"`,\nwithin the build container, to generate the build artefacts.\n\n`distro` (optional): the name of the directory containing the Dockerfile. By\ndefault, cqfd uses `\"docker\"`, and `.cqfd/docker/Dockerfile` is used.\n\n`user_extra_groups` (optional): a space-separated list of groups the user\nshould be a member of in the container. You can either use the `group:gid`\nformat, or simply specify the `group` name if it exists either in the host or\ninside the docker image.\n\n`flavors` (optional): the list of build flavors (see below). Each flavor has\nits own command just like `build.command`. This property is now automatically\ndeduced from the flavors sections of `.cqfdrc`.\n\n`docker_build_args` (optional): arguments used to invoke `docker build`.\nFor example, to attempt to pull newer version of the image, it can be set like:\n```\ndocker_build_args='--pull=true'\n```\n\n`docker_run_args` (optional): arguments used to invoke `docker run`.\nFor example, to share networking with the host, it can be set like:\n```\ndocker_run_args='--network=host'\n```\n\n`docker_rmi_args` (optional): arguments used to invoke `docker rmi`.\nFor example, to force removal of the image, it can be set like:\n```\ndocker_rmi_args='--force'\n```\n\n#### `cqfd release`\n\n`files`: the space-separated list of files generated by the build process\nthat we want to include inside a standard release archive.\n\n`archive` (optional): the name of the release archive generated by cqfd. You\ncan include environment variable names, as well as the following template\nmarks:\n\n* `%Gh` - git short hash of last commit\n* `%GH` - git long hash of last commit\n* `%D3` - RFC3339 date (YYYY-MM-DD)\n* `%Du` - Unix timestamp\n* `%Cf` - current cqfd flavor name (if any)\n* `%Po` - value of the `project.org` configuration key\n* `%Pn` - value of the `project.name` configuration key\n* `%%` - a litteral '%' sign\n\nBy default, cqfd will generate a release archive named\n`org-name.tar.xz`, where 'org' and 'name' come from the project's\nconfiguration keys. The .tar.xz, .tar.gz and .zip archive formats are\nsupported.\n\nFor tar archives:\n\n* Setting `tar_transform=yes` (optional) will cause all files specified for\n  the archive to be stored at the root of the archive, which is desired in some\n  scenarios.\n\n* Setting `tar_options` (optional) will pass extra options to the tar\n  command. For example, setting `tar_options=-h` will copy all symlink files\n  as hardlinks, which is desired in some scenarios.\n\n### Using build flavors\n\nIn some cases, it may be desirable to build the project using\nvariations of the build and release methods (for example a debug\nbuild). This is made possible in cqfd with the build flavors feature.\n\nIn the `.cqfdrc` file, one or more flavors may be listed in the\n`[build]` section, referencing other sections named following\nflavor's name.\n\n    [centos7]\n    command='make CENTOS=1'\n    distro='centos7'\n\n    [debug]\n    command='make DEBUG=1'\n    files='myprogram Symbols.map'\n\n    [build]\n    command='make'\n    files='myprogram'\n\nA flavor will typically redefine some keys of the build section:\ncommand, files, archive, distro.\n\nFlavors from a `.cqfdrc` file can be listed using the `flavors` argument.\n\n## cqfd features\n\n### Environment variables\n\nThe following environment variables are supported by cqfd to provide\nthe user with extra flexibility during his day-to-day development\ntasks:\n\n`CQFD_DOCKER`: program used to invoke `docker` client.\nFor example, to use docker if not in the docker group, it can be set like:\n```\nCQFD_DOCKER='sudo docker'\n```\n\n`CQFD_EXTRA_RUN_ARGS`: A space-separated list of additional\ndocker-run options to be append to the starting container.\nFormat is the same as (and passed to) docker-run’s options.\nSee 'docker run --help'.\n\n`CQFD_EXTRA_BUILD_ARGS`: A space-separated list of additional\ndocker-build options to be append to the building image.\nFormat is the same as (and passed to) docker-build’s options.\nSee 'docker build --help'.\n\n`CQFD_EXTRA_RMI_ARGS`: A space-separated list of additional\ndocker-rmi options to be append to the removed image.\nFormat is the same as (and passed to) docker-rmi’s options.\nSee 'docker rmi --help'.\n\n`CQFD_NO_SSH_CONFIG`: Set to `true` to disable forwarding the global\n`/etc/ssh` configurations to the container. This may be required if\nthe host's `ssh` configuration is not compatible with the `ssh`\nversion within the container.\n\n`CQFD_NO_USER_SSH_CONFIG`: Set to `true` to disable forwarding\nthe user's `~/.ssh` configuration to the container.\n\n`CQFD_NO_USER_GIT_CONFIG`: Set to `true` to disable forwarding\nthe user's `~/.gitconfig` configuration to the container.\n\n`CQFD_NO_SSH_AUTH_SOCK`: Set to `true` to disable forwarding the\nSSH authentication socket to the container.\n\n`CQFD_BIND_DOCKER_SOCK`: Set to `true` to enable forwarding the\ndocker socket to the container.\n\n`CQFD_DOCKER_GID`: The gid of the docker group in host to map to\nthe cqfd group in the container.\n\n`CQFD_SHELL`: The shell to be launched, by default `/bin/sh`.\n\n`CQFD_DISABLE_SHELL_HISTORY`: Set to `true` to disable bind mounting the shell\nhistory file in the container and setting the HISTFILE variable\n\n### Appending to the build command\n\nThe `-c` option set immediately after the command run allows appending the\ncommand of a cqfd run for temporary developments:\n\n    $ cqfd -b centos7 run -c \"clean\"\n    $ cqfd -b centos7 run -c \"TRACING=1\"\n\n### Running a shell in the container\n\nYou can use the `shell` command to quickly pop a shell in your defined\ncontainer. The shell to be launched (default `/bin/sh`) can be customized using\nthe `CQFD_SHELL` environment variable.\n\nExample:\n\n    fred@host:~/project$ cqfd shell\n    fred@container:~/project$\n\n### Use cqfd as an interpreter for shell script\n\nYou can use the `shell` command to write a shell script and run it in your\ndefined container.\n\nExample:\n\n    fred@host:~/project$ cat get-container-pretty-name.sh \n    #!/usr/bin/env -S cqfd shell\n    if ! test -e /.dockerenv; then\n        exit 1\n    fi\n    source /etc/os-release\n    echo \"$PRETTY_NAME\"\n    fred@host:~/projet$ ./get-container-pretty-name.sh \n    Debian GNU/Linux 12 (bookworm)\n\n### Use cqfd as a standard shell for binaries\n\nYou can even use the `shell` command to use it as a standard `$SHELL` so\nbinaries honoring that variable run shell commands in your defined container.\n\nExample:\n\n    fred@host:~/project$ make SHELL=\"cqfd shell\"\n    Available make targets:\n       help:      This help message\n       install:   Install script, doc and resources\n       uninstall: Remove script, doc and resources\n       tests:     Run functional tests\n\n### Other command-line options\n\nIn some conditions you may want to use alternate cqfd filenames and / or an\nexternal working directory. These options can be used to control the cqfd\nconfiguration files:\n\nThe working directory can be changed using the `-C` option:\n\n    $ cqfd -C external/directory\n\nAn alternate cqfd directory can be specified with the `-d` option:\n\n    $ cqfd -d cqfd_alt\n\nAn alternate cqfdrc file can be specified with the `-f` option:\n\n    $ cqfd -f cqfdrc_alt\n\nThese options can be combined:\n\n    $ cqfd -C external/directory -d cqfd_alt -f cqfdrc_alt\n    $ # cqfd will use:\n    $ #  - cqfd directory: external/directory/cqfd_alt\n    $ #  - cqfdrc file: external/directory/cqfdrc_alt\n\n### Shell history\n\n`cqfd` bind mounts the current shell history file to the container so the\ncommands history is shared between the user and the cqfd container. This feature\nis supported for `bash`, `zsh`, `tcsh`, and `ksh`.\n\nThis feature is available only when using the commands `cqfd shell`, `cqfd \u003cname_of_the_shell\u003e`\nsuch as `cqfd bash`, `cqfd run \u003cname_of_the_shell\u003e` and\n`cqfd exec \u003cname_of_the_shell\u003e`.\n\n## Build Container Environment\n\nWhen cqfd runs, a docker container is launched as the environment in\nwhich to run the *command*.  Within this environment, commands are run\nas the same user as the one invoking cqfd (with a fallback to the\n'builder' user in case it cannot be determined). So that this user has\naccess to local files, the current working directory is mapped to\nthe same location inside the container.\n\n### SSH Handling\n\nThe local ~/.ssh directory is also mapped to the corresponding\ndirectory in the build container. This effectively enables SSH agent\nforwarding so a build can, for example, pull authenticated git repos.\n\n### Terminal job control\n\nWhen cqfd runs a command as the unprivileged user that called it in\nthe first place, `su(1)` is used to run the command. This brings a\nlimitation for processes that require a controlling terminal (such as\nan interactive shell), as `su` will prevent the command executed\nfrom having one.\n\n```\n$ cqfd bash\nbash: cannot set terminal process group (-1): Inappropriate ioctl for device\nbash: no job control in this shell\n```\n\nTo work around this limitation, cqfd will use `sudo(8)` when it is\navailable in the container instead. The user is responsible for\nincluding it in the related Dockerfile.\n\n## Remove images\n\nRunning `cqfd init` creates and names a new Docker image each\ntime the Dockerfile is modified, which may lead to a large number of\nunused images that are not automatically purged.\n\nTo remove the image associated with the current version of the Dockerfile, use:\n\n    $ cqfd deinit\n\nIf a flavor redefines the distro key of the build section, use:\n\n    $ cqfd -b centos7 deinit\n\n## Requirements\n\nTo use cqfd, ensure the following requirements are satisfied on your\nworkstation:\n\n- Bash\n- Docker\n- A `docker` group in your `/etc/group`\n- Your username is a member of the `docker` group\n- Restart your docker service if you needed to create the group.\n\n## Installing/removing cqfd\n\n### From packages\n\n#### Arch Linux or Manjaro\n\nFirst download the package:\n\n    $ curl -LO https://github.com/savoirfairelinux/cqfd/releases/download/v5.8.0/cqfd-5.8.0-1-any.pkg.tar.zst\n\nThen, install it using the package manager:\n\n    $ sudo pacman -U ./cqfd-5.8.0-1-any.pkg.tar.zst\n\n_Note_: Uninstall it using the package manager:\n\n    $ sudo pacman -R cqfd\n\n#### Debian or Ubuntu\n\nFirst download the package:\n\n    $ curl -LO https://github.com/savoirfairelinux/cqfd/releases/download/v5.8.0/cqfd_5.8.0_all.deb\n\nThen, install it using the package manager:\n\n    $ sudo dpkg -i ./cqfd_5.8.0_all.deb\n\n_Note_: Uninstall it using the package manager:\n\n    $ sudo dpkg -r cqfd\n\n#### RedHat Linux or Fedora\n\nFirst download the package:\n\n    $ curl -LO https://github.com/savoirfairelinux/cqfd/releases/download/v5.8.0/cqfd-5.8.0-1.noarch.rpm\n\nThen, install it using the package manager:\n\n    $ sudo dnf install ./cqfd-5.8.0-1.noarch.rpm\n\n_Note_: Uninstall it using the package manager:\n\n    $ sudo dnf remove cqfd\n\n### From source\n\nFirst clone this repository:\n\n    $ git clone https://github.com/savoirfairelinux/cqfd.git\n    $ git submodule update --init --recursive\n\nThen, install the script and its resources:\n\n    $ make install\n\nFinally, uninstall the script and its resources:\n\n    $ make uninstall\n\nMakefile honors both **PREFIX** (__/usr/local__) and **DESTDIR** (__[empty]__)\nvariables:\n\n    $ make install PREFIX=/opt\n    $ make install PREFIX=/usr DESTDIR=package\n\n### GNU Guix\n\nIf you use the [GNU Guix](https://gnu.org/software/guix) package\nmanager, you can install `cqfd` via:\n\n```sh\nguix install cqfd\n```\n\n### Arch Linux or Manjaro\n\nIf you use an Arch Linux derivative distribution based on pacman package\nmanager, you can build the latest released version of the `cqfd` package via:\n\n```sh\nmakepkg\n```\n\nOr, the current unreleased version of the `cqfd-git` package via:\n\n```sh\nmakepkg -f PKGBUILD-git\n```\n\n_Note_: The artefacts are available in the current directory.\n\n### Debian or Ubuntu\n\nIf you use an Debian derivative distribution based on the dpkg package manager,\nyou can build the latest released version of the `cqfd` package via:\n\n```sh\ndpkg-buildpackage -us -uc\n```\n\n_Note_: The artefacts are available in the parent directory.\n\n### RedHat Linux or Fedora\n\nIf you use a RPM based distribution, you can build the latest released version\nof the `cqfd` package via:\n\n```sh\nrpmdev-setuptree\ncp cqfd.spec ~/rpmbuild/SPECS/\ncd ~/rpmbuild/SPECS\nrpmbuild --undefine=_disable_source_fetch -ba cqfd.spec \"$@\"\ncp ~/rpmbuild/SRPMS/*.src.rpm ~/rpmbuild/RPMS/*/*.rpm \"$OLDPWD\"\n```\n\n_Note_: The artefacts are available in `~/rpmbuild/RPMS` and `~/rpmbuild/SRPMS`\ndirectories.\n\n## Using podman\n\nPodman may be used instead of Docker. It first must be installed on your system,\nand then, to use it instead of docker, you can set in your environment,\nlike your `.bashrc`, `.profile` or `.zshrc`:\n\n```bash\nexport CQFD_DOCKER=\"podman\"\n```\n\nYou can also prefix your cqfd commands:\n\n```bash\nCQFD_DOCKER=\"podman\" cqfd init\nCQFD_DOCKER=\"podman\" cqfd shell\n```\n\n## Testing cqfd (for developers)\n\nThe codebase contains tests which can be invoked using the following\ncommand, if the [requirements](#requirements) are met on the system:\n\n    $ make tests\n\nThe test suite depends on a git submodule, so if they do not run it may be\nbecause submodule have not been synced. To sync them, use:\n\n    $ git submodule update --init --recursive\n\n## Patches\n\nSubmit patches at *https://github.com/savoirfairelinux/cqfd/pulls*\n\n## Bugs\n\nReport bugs at *https://github.com/savoirfairelinux/cqfd/issues*\n\n## Trivia\n\nCQFD stands for \"ce qu'il fallait Dockeriser\", French for \"what needed\nto be Dockerized\".\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsavoirfairelinux%2Fcqfd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsavoirfairelinux%2Fcqfd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsavoirfairelinux%2Fcqfd/lists"}