Skip to content

Commit 244664d

Browse files
committed
WIP: fact docker compose
1 parent e39728e commit 244664d

File tree

7 files changed

+211
-7
lines changed

7 files changed

+211
-7
lines changed

Dockerfile

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
FROM nestybox/ubuntu-noble-systemd-docker@sha256:8b1c4409fe89bc110e1e468767074fe4403ba6bb2d1b34881fec5df8b6c2f9c3 AS fact_base
2+
3+
ARG FACT_DIR=/opt/fact
4+
COPY src $FACT_DIR
5+
WORKDIR $FACT_DIR
6+
7+
RUN --mount=type=cache,target=/var/cache/apt \
8+
--mount=type=cache,target=/var/lib/apt \
9+
apt-get update && \
10+
apt-get install -y --no-install-recommends \
11+
curl \
12+
python3-venv \
13+
postgresql-client \
14+
redis-tools
15+
16+
RUN python3 -m venv venv
17+
ARG VENV_DIR=$FACT_DIR/venv/bin
18+
ENV PATH=$VENV_DIR:$PATH \
19+
VIRTUAL_ENV=$VENV_DIR \
20+
PYTHONPATH=$FACT_DIR \
21+
FACT_INSTALLER_SKIP_DOCKER=1
22+
23+
RUN --mount=type=cache,target=/var/cache/apt \
24+
--mount=type=cache,target=/var/lib/apt \
25+
./install/pre_install.sh -D
26+
27+
FROM fact_base AS fact_frontend
28+
29+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
30+
--mount=type=cache,target=/var/lib/apt,sharing=locked \
31+
python3 install.py -F -H
32+
33+
RUN chown -R admin:admin "$FACT_DIR"
34+
35+
COPY --chown=admin docker/entrypoint_frontend.sh .
36+
37+
ENTRYPOINT ["./entrypoint_frontend.sh"]
38+
39+
FROM fact_base AS fact_backend
40+
41+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
42+
--mount=type=cache,target=/var/lib/apt,sharing=locked \
43+
python3 install.py -B
44+
45+
RUN chown -R admin:admin "$FACT_DIR"
46+
47+
COPY --chown=admin docker/entrypoint_backend.sh .
48+
49+
# This file serves as a flag to indicate that the backend installation of the docker containers is completed
50+
RUN touch DOCKER_INSTALL_INCOMPLETE
51+
# We must still install the docker images, so we need to overwrite the flag now:
52+
ENV FACT_INSTALLER_SKIP_DOCKER=0
53+
54+
ENTRYPOINT ["./entrypoint_backend.sh"]

README.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,30 @@ our [tutorial](https://github.com/fkie-cad/FACT_core/blob/master/INSTALL.vagrant
114114

115115
### Docker
116116

117-
There is also a dockerized version, but it is currently unmaintained.
118-
(see the [FACT_docker](https://github.com/fkie-cad/FACT_docker) repo for more information).
117+
>[!IMPORTANT]
118+
> The docker image requires Sysbox as Docker runtime.
119+
> Sysbox installation is described [here](https://github.com/nestybox/sysbox/tree/master?tab=readme-ov-file#installation)
120+
> Please make sure that it works before trying to run FACT with docker by running the hello-world image:
121+
> `docker run --rm --runtime sysbox-runc hello-world`
122+
123+
If you have untracked files in the directory or also installed FACT locally, create a `.dockerignore`, so you don't
124+
copy the files into the Docker image when building it:
125+
126+
```shell
127+
# exclude untracked files:
128+
git ls-files . --exclude-standard --others --directory > .dockerignore
129+
# exclude ignored files:
130+
git ls-files . --ignored --exclude-standard --others --directory >> .dockerignore
131+
# also exclude the .git folder:
132+
echo ".git/" >> .dockerignore
133+
```
134+
135+
Running FACT with docker compose:
136+
137+
```shell
138+
docker compose build
139+
docker compose up
140+
```
119141

120142
## Usage
121143

docker-compose.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
services:
2+
fact-frontend:
3+
runtime: sysbox-runc
4+
build:
5+
context: .
6+
target: fact_frontend
7+
environment:
8+
PGPASSWORD: password
9+
ports:
10+
- "5000:5000"
11+
networks:
12+
fact:
13+
aliases:
14+
- frontend
15+
fact-backend:
16+
runtime: sysbox-runc
17+
build:
18+
context: .
19+
target: fact_backend
20+
environment:
21+
PGPASSWORD: password
22+
networks:
23+
fact:
24+
aliases:
25+
- backend
26+
volumes:
27+
- fact_files:/media/data
28+
db:
29+
container_name: postgres
30+
image: postgres:17
31+
environment:
32+
POSTGRES_USER: postgres
33+
POSTGRES_PASSWORD: password
34+
PGDATA: /data/postgres
35+
volumes:
36+
- fact_db:/data/postgres
37+
networks:
38+
fact:
39+
aliases:
40+
- db
41+
restart: unless-stopped
42+
healthcheck:
43+
test: [ "CMD-SHELL", "pg_isready -d postgres" ]
44+
interval: 30s
45+
timeout: 10s
46+
retries: 5
47+
redis:
48+
container_name: redis
49+
image: redis:alpine
50+
restart: always
51+
networks:
52+
fact:
53+
aliases:
54+
- redis
55+
56+
networks:
57+
fact:
58+
driver: bridge
59+
60+
volumes:
61+
fact_db:
62+
fact_files:

docker/entrypoint_backend.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
3+
set -eux
4+
5+
# start docker service
6+
dockerd &
7+
8+
# redis runs in a different container => replace "localhost" with "redis"
9+
sed -i 's/host = "localhost"/host = "redis"/g' /opt/fact/config/fact-core-config.toml
10+
# postgres also runs in a different container => replace "localhost" with "db"
11+
sed -i 's/server = "localhost"/server = "db"/g' /opt/fact/config/fact-core-config.toml
12+
13+
until redis-cli -h redis ping | grep -q PONG; do
14+
echo "Waiting for Redis to start..."
15+
sleep 2
16+
done
17+
echo "Found Redis container"
18+
19+
until pg_isready -h db -U postgres; do
20+
echo "Waiting for PostgreSQL to start..."
21+
sleep 2
22+
done
23+
echo "Found PostgreSQL container"
24+
25+
if [ -e DOCKER_INSTALL_INCOMPLETE ]; then
26+
echo "Installing FACT docker images..."
27+
python3 install.py --backend-docker-images
28+
rm DOCKER_INSTALL_INCOMPLETE
29+
echo "FACT docker image installation completed"
30+
fi
31+
32+
until curl -s -X GET 'http://frontend:5000/rest/status'; do
33+
echo "Waiting for FACT frontend to start..."
34+
sleep 2
35+
done
36+
echo "FACT frontend is ready"
37+
38+
python3 start_fact_backend.py

docker/entrypoint_frontend.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env bash
2+
3+
set -eux
4+
5+
# start docker service
6+
dockerd &
7+
8+
# redis runs in a different container => replace "localhost" with "redis"
9+
sed -i 's/host = "localhost"/host = "redis"/g' /opt/fact/config/fact-core-config.toml
10+
# postgres also runs in a different container => replace "localhost" with "db"
11+
sed -i 's/server = "localhost"/server = "db"/g' /opt/fact/config/fact-core-config.toml
12+
# replace localhost with 0.0.0.0 in uWSGI config so that the frontend can be reached from outside
13+
sed -i 's/127.0.0.1/0.0.0.0/g' /opt/fact/config/uwsgi_config.ini
14+
15+
until redis-cli -h redis ping | grep -q PONG; do
16+
echo "Waiting for Redis to start..."
17+
sleep 2
18+
done
19+
echo "Found Redis container"
20+
21+
until pg_isready -h db -U postgres; do
22+
echo "Waiting for PostgreSQL to start..."
23+
sleep 2
24+
done
25+
echo "Found PostgreSQL container"
26+
27+
# init the DB
28+
python3 init_postgres.py
29+
30+
python3 start_fact_frontend.py --no-radare

src/init_postgres.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ def user_exists(user_name: str, host: str, port: str | int) -> bool:
4343

4444
def create_admin_user(user_name: str, password: str, host: str, port: int | str):
4545
execute_psql_command(
46-
# fmt: off
47-
(f"CREATE USER {user_name} WITH PASSWORD '{password}' " 'LOGIN SUPERUSER INHERIT CREATEDB CREATEROLE;'),
48-
# fmt: on
46+
f"CREATE USER {user_name} WITH PASSWORD '{password}' LOGIN SUPERUSER INHERIT CREATEDB CREATEROLE;",
4947
host=host,
5048
port=port,
5149
)

src/install.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
PROGRAM_VERSION = '1.2'
4444
PROGRAM_DESCRIPTION = 'Firmware Analysis and Comparison Tool (FACT) installation script'
4545

46-
FACT_INSTALLER_SKIP_DOCKER = os.getenv('FACT_INSTALLER_SKIP_DOCKER')
46+
FACT_INSTALLER_SKIP_DOCKER = bool(int(os.getenv('FACT_INSTALLER_SKIP_DOCKER', '0')))
4747

4848

4949
def _setup_argparser():
@@ -169,7 +169,7 @@ def install():
169169
welcome()
170170
none_chosen = not (args.frontend or args.db or args.backend or args.common)
171171
# TODO maybe replace this with an cli argument
172-
skip_docker = FACT_INSTALLER_SKIP_DOCKER is not None
172+
skip_docker = FACT_INSTALLER_SKIP_DOCKER
173173
# Note that the skip_docker environment variable overrides the cli argument
174174
only_docker = not skip_docker and none_chosen and (args.backend_docker_images or args.frontend_docker_images)
175175

0 commit comments

Comments
 (0)