{"id":13418254,"url":"https://github.com/Cisco-Talos/clamav","last_synced_at":"2025-03-15T03:30:47.076Z","repository":{"id":4027813,"uuid":"5128084","full_name":"Cisco-Talos/clamav","owner":"Cisco-Talos","description":"ClamAV - Documentation is here: https://docs.clamav.net","archived":false,"fork":false,"pushed_at":"2024-10-23T17:03:24.000Z","size":177574,"stargazers_count":4359,"open_issues_count":271,"forks_count":700,"subscribers_count":136,"default_branch":"main","last_synced_at":"2024-10-29T15:09:15.815Z","etag":null,"topics":["antivirus","clamav","gplv2","open-source"],"latest_commit_sha":null,"homepage":"https://www.clamav.net/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cisco-Talos.png","metadata":{"files":{"readme":"README.Docker.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":"COPYING.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-07-20T20:37:54.000Z","updated_at":"2024-10-29T07:19:40.000Z","dependencies_parsed_at":"2023-07-05T18:02:16.422Z","dependency_job_id":"a8b66947-ade9-41c2-a4b7-fd185535f780","html_url":"https://github.com/Cisco-Talos/clamav","commit_stats":{"total_commits":10753,"total_committers":145,"mean_commits":74.15862068965517,"dds":0.7888961220124616,"last_synced_commit":"f79f9421504375d1f970636a891681a67c5dea2a"},"previous_names":["cisco-talos/clamav-devel","vrtadmin/clamav-devel"],"tags_count":236,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cisco-Talos%2Fclamav","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cisco-Talos%2Fclamav/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cisco-Talos%2Fclamav/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cisco-Talos%2Fclamav/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cisco-Talos","download_url":"https://codeload.github.com/Cisco-Talos/clamav/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243681024,"owners_count":20330152,"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":["antivirus","clamav","gplv2","open-source"],"created_at":"2024-07-30T22:01:00.153Z","updated_at":"2025-03-15T03:30:45.314Z","avatar_url":"https://github.com/Cisco-Talos.png","language":"C","funding_links":[],"categories":["TODO scan for Android support in followings","C","Uncategorized","Malware Detection","Security","Table of Contents","Map of the content"],"sub_categories":["Uncategorized","Antivirus","Security"],"readme":"# ClamAV in Docker\n\nClamAV can be run within a Docker container. This provides isolation from other\nprocesses by running it in a containerized environment. If new or unfamiliar\nwith Docker, containers or cgroups see [docker.com](https://www.docker.com).\n\n## The official images on Docker Hub\n\nClamAV image tags [on Docker Hub](https://hub.docker.com/u/clamav/clamav)\nfollow this naming convention:\n\n  - `clamav/clamav:\u003cversion\u003e`: A release preloaded with signature databases.\n\n    Using this container will save the ClamAV project some bandwidth.\n    Use this if you will keep the image around so that you don't download the\n    entire database set every time you start a new container. Updating with\n    FreshClam from existing databases set does not use much data.\n\n  - `clamav/clamav:\u003cversion\u003e_base`: A release with no signature databases.\n\n    Use this container **only** if you mount a volume in your container under\n    `/var/lib/clamav` to persist your signature database databases.\n    This method is the best option because it will reduce data costs for ClamAV\n    and for the Docker registry, but it does require advanced familiarity with\n    Linux and Docker.\n\n    \u003e _Caution_: Using this image without mounting an existing database\n    directory will cause FreshClam to download the entire database set each\n    time you start a new container.\n\nYou can use the `unstable` version (i.e. `clamav/clamav:unstable` or\n`clamav/clamav:unstable_base`) to try the latest from our development branch.\n\n## Building the ClamAV image\n\nWhile it is recommended to pull the image from our\n[Docker Hub registry](https://hub.docker.com/u/clamav/clamav), some may want\nto build the image locally instead.\n\nTo do this, you will need to get the  `Dockerfile` and the supporting `scripts/`\ndirectory from the\n[clamav-docker Git repository](https://github.com/Cisco-Talos/clamav-docker).\nBe sure to select the correct one for this ClamAV release.\n\n\u003e _Tip_: For unreleased ClamAV versions, such as when building from the `main`\n\u003e git branch, you should select the files from the\n\u003e `clamav-docker/clamav/unstable/\u003cdistro\u003e` directory.\n\nPlace the `Dockerfile` and `scripts/` directory in the ClamAV source directory.\nThen you can build the image. For example, run:\n```bash\ndocker build --tag \"clamav:TICKET-123\" .\n```\nin the current directory. This will build the ClamAV image and tag it with\nthe name \"clamav:TICKET-123\". Any name can generally be used and it is this\nname that needs to be referred to later when running the image.\n\n## Running ClamD\n\nTo run `clamd` in a Docker container, first, an image either has to be built\nor pulled from a Docker registry.\n\n### Running ClamD using the official ClamAV images from Docker Hub\n\nTo pull the ClamAV \"unstable\" image from Docker Hub, run:\n\n```bash\ndocker pull clamav/clamav:unstable\n```\n\n\u003e _Tip_: Substitute `unstable` with a different version as needed.\n\nTo pull _and run_ the official ClamAV images from the Docker Hub registry,\ntry the following command:\n\n```bash\ndocker run \\\n    --interactive \\\n    --tty \\\n    --rm \\\n    --name \"clam_container_01\" \\\n    clamav/clamav:unstable\n```\n\nThe above creates an interactive container with the current TTY connected to\nit. This is optional but useful when getting started as it allows one to\ndirectly see the output and, in the case of `clamd`, send `ctrl-c` to close the\ncontainer. The `--rm` parameter ensures the container is cleaned up again after\nit exits and the `--name` parameter names the container, so it can be\nreferenced through other (Docker) commands, as several containers of the same\nimage can be started without conflicts.\n\n\u003e _Note_: Pulling is not always required. `docker run` will pull the image\nif it cannot be found locally. `docker run --pull always` will always pull\nbeforehand to ensure the most up-to-date container is being used.\nDo not use `--pull always` with the larger ClamAV images.\n\n\u003e _Tip_: It's common to see `-it` instead of `--interactive --tty`.\n\nIn some situations it may be desirable to set (any of) the containers to a\nspecific timezone. The `--env` parameter can be used to set the `TZ` variable\nto change the default of `Etc/UTC`.\n\n### Running ClamD using a Locally Built Image\n\nYou can run a container using an image built locally\n([see \"Building the ClamAV Image\"](#building-the-clamav-image)). Just run:\n```bash\ndocker run -it --rm \\\n    --name \"clam_container_01\" \\\n    clamav:TICKET-123\n```\n\n### Persisting the virus database (volume)\n\nThe virus database in `/var/lib/clamav` is by default unique to each container\nand thus is normally not shared. For simple setups this is fine, where only one\ninstance of `clamd` is expected to run in a dockerized environment. However\nsome use cases may want to efficiently share the database or at least persist\nit across short-lived ClamAV containers.\n\nTo do so, you have two options:\n\n1. Create a [Docker volume](https://docs.docker.com/storage/volumes/) using the\n   `docker volume` command.\n   Volumes are completely managed by Docker and are the best choice for\n   creating a persistent database volume.\n\n   For example, create a \"clam_db\" volume:\n   ```bash\n   docker volume create clam_db\n   ```\n\n   Then start one or more containers using this volume. The first container\n   to use a new database volume will download the full database set. Subsequent\n   containers will use the existing databases and may update them as needed:\n   ```bash\n   docker run -it --rm \\\n       --name \"clam_container_01\" \\\n       --mount source=clam_db,target=/var/lib/clamav \\\n       clamav/clamav:unstable_base\n   ```\n\n2. Create a [Bind Mount](https://docs.docker.com/storage/bind-mounts/) that\n   maps a file system directory to a path within the container.\n   Bind Mounts depend on the directory structure, permissions, and operating\n   system of the Docker host machine.\n\n   Run the container with these arguments to mount the a directory from your host\n   environment as a volume in the container.\n   ```bash\n       --mount type=bind,source=/path/to/databases,target=/var/lib/clamav\n   ```\n\n   When doing this, it's best to use the `\u003cversion\u003e_base` image tags so as to\n   save on bandwidth. E.g.:\n   ```bash\n   docker run -it --rm \\\n       --name \"clam_container_01\" \\\n       --mount type=bind,source=/path/to/databases,target=/var/lib/clamav \\\n       clamav/clamav:unstable_base\n   ```\n\n   \u003e _Disclaimer_: When using a Bind Mount, the container's entrypoint script\n   will change ownership of this directory to its \"clamav\" user. This enables\n   FreshClam and ClamD with the required permissions to read and write to the\n   directory, though these changes will also affect those files on the host.\n\nIf you're thinking about running multiple containers that share a single\ndatabase volume, [here are some notes on how this might work](#multiple-containers-sharing-the-same-mounted-databases).\n\n## Running Clam(D)Scan\n\nScanning files using `clamscan` or `clamdscan` is possible in various ways with\nDocker. This section briefly describes them, but the other sections of this\ndocument are best read before hand to better understand some of the concepts.\n\nOne important aspect is however to realize that Docker by default does not have\naccess to any of the hosts files. And so to scan these within Docker, they need\nto be mounted with a [bind mount](https://docs.docker.com/storage/bind-mounts/)\nto be made accessible.\n\nFor example, running the container with these arguments ...\n```bash\n    --mount type=bind,source=/path/to/scan,target=/scandir\n    --mount type=bind,source=/path/to/scan,target=/scandir\n```\n... would make the hosts file/directory `/path/to/scan` available in the\ncontainer as `/scandir` and thus invoking `clamscan` would thus be done on\n`/scandir`.\n\nNote that while technically possible to run either scanners via `docker exec`\nthis is not described as it is unlikely the container has access to the files\nto be scanned.\n\n### ClamScan\n\nUsing `clamscan` outside of the Docker container is how normally `clamscan` is\ninvoked. To make use of the available shared dockerized resources however, it\nis possible to expose the virus database and share that for example. E.g. it\ncould be possible to run a Docker container with only the `freshclam` daemon\nrunning, and share the virus database directory `/var/lib/clamav`. This could\nbe useful for file servers for example, where only `clamscan` is installed on\nthe host, and `freshclam` is managed in a Docker container.\n\n\u003e _Note_: Running the `freshclam` daemon separated from `clamd` is less\nrecommended, unless the `clamd` socket is shared with `freshclam` as\n`freshclam` would not be able to inform `clamd` of database updates.\n\n### Dockerized ClamScan\n\nTo run `clamscan` in a Docker container, the Docker container can be invoked\nas:\n```bash\ndocker run -it --rm \\\n    --mount type=bind,source=/path/to/scan,target=/scandir \\\n    clamav/clamav:unstable \\\n    clamscan /scandir\n```\n\nHowever, this will use whatever signatures are found in the image, which may be\nslightly out of date. If using `clamscan` in this way, it would be best to use\na [database volume](#running-with-a-mounted-database-directory-volume) that is\nup-to-date so that you scan with the latest signatures. E.g.:\n```bash\ndocker run -it --rm \\\n    --mount type=bind,source=/path/to/scan,target=/scandir \\\n    --mount type=bind,source=/path/to/databases,target=/var/lib/clamav \\\n    clamav/clamav:unstable_base \\\n    clamscan /scandir\n```\n\n### ClamDScan\n\nAs with `clamscan`, `clamdscan` can also be run when installed on the host, by\nconnecting to the dockerized `clamd`. This can be done by either pointing\n`clamdscan` to the exposed TCP/UDP port or unix socket.\n\n### Dockerized ClamDScan\n\nRunning both `clamd` and `clamdscan` is also easily possible, as all that is\nneeded is the shared socket between the two containers. The only caveat here\nis to:\n1. mount the files to be scanned in the container that will run `clamd`, or\n2. mount the files to be scanned in the container that will `clamdscan` run if\n   using `clamdscan --stream`. The `--stream` option will be slower, but\n   enables submitting files from a different machine on a network.\n\nFor example:\n```bash\ndocker run -it --rm \\\n    --mount type=bind,source=/path/to/scan,target=/scandir \\\n    --mount type=bind,source=/var/lib/docker/data/clamav/sockets/,target=/run/clamav/\n    clamav/clamav:unstable\n```\n\n```bash\ndocker run -it --rm \\\n    --mount type=bind,source=/path/to/scan,target=/scandir \\\n    --mount type=bind,source=/var/lib/docker/data/clamav/sockets/,target=/run/clamav/\n    clamav/clamav:unstable_base \\\n    clamdscan /scandir\n```\n\n## Controlling the container\n\nThe ClamAV container actually runs both `freshclam` and `clamd` daemons by\ndefault. Optionally available to the container is ClamAV's milter daemon.\nTo control the behavior of the services started within the container, the\nfollowing flags can be passed to the `docker run` command with the\n`--env` (`-e`) parameter.\n\n* CLAMAV_NO_CLAMD [true|**false**] Do not start `clamd`.\n  (default: start `clamd`)\n* CLAMAV_NO_FRESHCLAMD [true|**false**] Do not start the `freshclam` daemon.\n  (default: start the `freshclam` daemon)\n* CLAMAV_NO_MILTERD [**true**|false] Do not start the `clamav-milter` daemon.\n  (default: start the `clamav-milter` daemon )\n* CLAMD_STARTUP_TIMEOUT [integer] Seconds to wait for `clamd` to start.\n  (default: 1800)\n* FRESHCLAM_CHECKS [integer] `freshclam` daily update frequency.\n  (default: once per day)\n\nSo to additionally also enable `clamav-milter`, the following flag can be\nadded:\n```bash\n    --env 'CLAMAV_NO_MILTERD=false'\n```\n\nFurther more, all of the configuration files that live in `/etc/clamav` can be\noverridden by doing a volume-mount to the specific file. The following argument\ncan be added for this purpose. The example uses the entire configuration\ndirectory, but this can be supplied multiple times if individual files deem to\nbe replaced.\n```bash\n    --mount type=bind,source=/full/path/to/clamav/,target/etc/clamav\n```\n\n\u003e _Note_: Even when disabling the `freshclam` daemon, `freshclam` will always\nrun at least once during container startup if there is no virus database.\nWhile not recommended, the virus database location itself `/var/lib/clamav/`\ncould be a persistent Docker volume. This however is slightly more advanced\nand out of scope of this document.\n\n## Connecting to the container\n\n### Executing commands within a running container\n\nTo connect to a running ClamAV container, `docker exec` can be used to run a\ncommand on an already running container. To do so, the name needs to be either\nobtained from `docker ps` or supplied during container start via the `--name`\nparameter. The most interesting command in this case can be `clamdtop`.\n```bash\ndocker exec --interactive --tty \"clamav_container_01\" clamdtop\n```\nAlternatively, a shell can be started to inspect and run commands within the\ncontainer as well.\n```bash\ndocker exec --interactive --tty \"clamav_container_01\" /bin/sh\n```\n\n### Unix sockets\n\nThe default socket for `clamd` is located inside the container as\n`/run/clamav/clamd.sock` and can be connected to when exposed via a Docker\nvolume mount. To ensure, that `clamd` within the container can freely create\nand remove the socket, the path for the socket is to be volume-mounted, to\nexpose it for others on the same host to use. The following volume can be used\nfor this purpose. Do ensure that the directory on the host actually exists and\nclamav inside the container has permission to access it.\nCaution is required when managing permissions, as incorrect permission could\nopen clamd for anyone on the host system.\n```bash\n    --mount type=bind,source=/var/lib/docker/data/clamav/sockets/,target=/run/clamav/\n```\n\nWith the socket exposed to the host, any other service can now talk to `clamd`\nas well. If for example `clamdtop` where installed on the local host, calling\n```bash\nclamdtop \"/var/lib/docker/data/clamav/sockets/clamd.sock\"\n```\nshould work just fine. Likewise, running `clamdtop` in a different container,\nbut sharing the socket will equally work. While `clamdtop` works well as an\nexample here, it is of course important to realize, this can also be used to\nconnect a mail server to `clamd`.\n\n### TCP\n\nClamAV in the official Docker images is configured to listen for TCP\nconnections on these ports:\n- `clamd`: 3310\n- `clamav-milter`: 7357\n\nWhile `clamd` and `clamav-milter` will listen on the above TCP ports, Docker\ndoes not expose these by default to the host.\nOnly within containers can these ports be accessed. To expose, or \"publish\",\nthese ports to the host, and thus potentially over the (inter)network, the\n`--publish` (or `--publish-all`) flag to `docker run` can be used. While more\nadvanced/secure mappings can be done as per documentation, the basic way is to\n`--publish [\u003chost_port\u003e:]\u003ccontainer_port\u003e` to make the port available to the\nhost.\n```bash\n    --publish 73310:3310 \\\n    --publish 7357\n```\nThe above would thus publish the milter port 3310 as 73310 on the host and the\nclamd port 7357 as a random to the host. The random port can be inspected via\n`docker ps`.\n\n\u003e **Warning**: Extreme caution is to be taken when using `clamd` over TCP as\nthere are no protections on that level. All traffic is un-encrypted. Extra\ncare is to be taken when using TCP communications.\n\n## Container ClamD health-check\n\nDocker has the ability to run simple `ping` checks on services running inside\ncontainers. If `clamd` is running inside the container, Docker will on\noccasion send a `ping` to `clamd` on the default port and wait for the pong\nfrom `clamd`. If `clamd` fails to respond, Docker will treat this as an error.\nThe healthcheck results can be viewed with `docker inspect`.\n\nWhen the container starts up, the health-check also starts up. As loading the\nvirus database can take some time, there is a delay configured in the\n`Dockerfile` to try to avoid this race condition.\n\n## Performance\n\nThe performance impact of running `clamd` in Docker is negligible. Docker is\nin essence just a wrapper around Linux's cgroups and cgroups can be thought of\nas `chroot` or FreeBSD's `jail`. All code is executed on the host without any\ntranslation. Docker does however do some isolation (through cgroups) to isolate\nthe various systems somewhat.\n\nOf course, nothing in life is free, and so there is some overhead. Disk-space\nbeing the most prominent one. The Docker container might have some duplication\nof files for example between the host and the container. Further more, also RAM\nmemory may be duplicated for each instance, as there is no RAM-deduplication.\nBoth of which can be solved on the host however. A filesystem that supports\ndisk-deduplication and a memory manager that does RAM-deduplication.\n\nThe base container in itself is already very small ~16 MiB, at the time of this\nwriting, this cost is still very tiny, where the advantages are very much worth\nthe cost in general.\n\nThe container including the virus database is about ~240 MiB at the time of\nthis writing.\n\n## Bandwidth\n\nPlease, be kind when using 'free' bandwidth, both for the virus databases\nbut also the Docker registry. Try not to download the entire database set or\nthe larger ClamAV database images on a regular basis.\n\n## Advanced container configurations\n\n### Multiple containers sharing the same mounted databases\n\nYou can run multiple containers that share the same database volume, but be\naware that the FreshClam daemons on each would compete to update the databases.\nMost likely, one would update the databases and trigger its ClamD to load the\nnew databases, while the others would be oblivious to the new databases and\nwould continue with the old signatures until the next ClamD self-check.\n\nThis is fine, honestly. It won't take that long before the new signatures are\ndetected by ClamD's self-check and the databases are reloaded automatically.\n\nTo reload the databases on all ClamD containers immediately after an update,\nyou could [disable the FreshClam daemon](#controlling-the-container) when you\nstart the containers. Later, use `docker exec` to perform an update and again\nas needed to have ClamD load updated databases.\n\n\u003e _Note_: This really isn't necessary but you could do this if you wish.\n\nExactly how you orchestrate this will depend on your environment.\nYou might do something along these lines:\n\n1. Create a \"clam_db\" volume, if you don't already have one:\n   ```bash\n   docker volume create clam_db\n   ```\n\n2. Start your containers:\n   ```bash\n   docker run -it --rm \\\n       --name \"clam_container_01\" \\\n       --mount source=clam_db,target=/var/lib/clamav \\\n       --env 'CLAMAV_NO_FRESHCLAMD=true' \\\n       clamav/clamav:unstable_base\n   ```\n   Wait for the first one to download the databases (if it's a new database\n   volume). Then start more:\n   ```bash\n   docker run -it --rm \\\n       --name \"clam_container_02\" \\\n       --mount source=clam_db,target=/var/lib/clamav \\\n       --env 'CLAMAV_NO_FRESHCLAMD=true' \\\n       clamav/clamav:unstable_base\n   ```\n3. Check for updates, as needed:\n   ```bash\n   docker exec -it clam_container_01 freshclam --on-update-execute=EXIT_1 || \\\n   if [ $? == 1 ]; then \\\n       docker exec -it clam_container_01 clamdscan --reload; \\\n       docker exec -it clam_container_02 clamdscan --reload; \\\n   fi\n   ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCisco-Talos%2Fclamav","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCisco-Talos%2Fclamav","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCisco-Talos%2Fclamav/lists"}