Skip to content

Commit

Permalink
feat: dockerized deployment, including helper script to set up/tear d…
Browse files Browse the repository at this point in the history
…own Docker development environment
  • Loading branch information
PascalinDe committed Apr 3, 2024
1 parent 739a78b commit 4b61aa4
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 73 deletions.
21 changes: 21 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This is an example .env file with default passwords and private keys.
# Do not use this in production or with any public-facing ports!
BACKEND_HOST=backend # name of the 'backend' container
BACKEND_PORT=5000 # port of the 'backend' container
COMPOSE_FILE=./docker-compose/docker-compose.yml # Docker Compose configuration file to use
DATABASE_HOST=db # name of the PostgreSQL container
DATABASE_PASSWORD=Ohw0phoa # choose any PostgreSQL password
DATABASE_PORT=5432 # port of the PostgreSQL container
DATABASE_USERNAME=dvoting
DB_PATH=dvoting # LMDB database path
DELA_PROXY_URL=http://172.19.44.254:8080 # IP and port of one of the DELA containers
FRONT_END_URL=http://127.0.0.1:3000 # the automated frontend tests expect this value do not change it
NODEPORT=2000 # DELA node port
# For public-facing services and production, this key needs to be changed!
PRIVATE_KEY=6aadf480d068ac896330b726802abd0da2a5f3824f791fe8dbd4cd555e80b809
PROXYPORT=8080 # DELA proxy port
PUBLIC_KEY=3e5fcaed4c5d79a8eccceeb087ee0a13b8f91d917ed62017a9cd28e13b228389
REACT_APP_DEV_LOGIN=true # debugging admin login /!\ disable in production /!\
REACT_APP_RANDOMIZE_VOTE_ID=true # randomize voter ID for debugging /!\ disable in production /!\
REACT_APP_SCIPER_ADMIN=123456 # debugging admin ID /!\ disable in production /!\
SESSION_SECRET=kaibaaF9 # choose any secret
22 changes: 12 additions & 10 deletions Dockerfiles/Dockerfile.dela
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
FROM golang:1.20.6-bookworm AS base
RUN apt-get update && apt-get install git
# make sure we're using the same head as d-voting
RUN git clone https://github.com/c4dt/dela.git
WORKDIR /go/dela/cli/crypto
RUN go install
WORKDIR /go/d-voting
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY . .

FROM base AS build
COPY --from=base /go/dela .
COPY --from=base /go/d-voting .
ENV GOCACHE=/root/.cache/go-build
WORKDIR /go/d-voting/cli/dvoting
RUN go build
ENV PATH=/go/dela/cli/crypto:/go/d-voting/cli/dvoting:${PATH}
RUN --mount=type=cache,target="/root/.cache/go-build" go install
# make sure we're using the same head as d-voting
RUN --mount=type=cache,target="/root/.cache/go-build" cd $( go list -f '{{.Dir}}' go.dedis.ch/dela )/cli/crypto && go install

FROM golang:1.20.6-bookworm AS build
WORKDIR /usr/local/bin
COPY --from=base /go/bin/crypto .
COPY --from=base /go/bin/dvoting .
ENTRYPOINT ["/bin/bash", "-c", "dvoting --config /data/node start --postinstall --proxyaddr :$PROXYPORT --proxykey $PROXYKEY --listen tcp://0.0.0.0:2000 --public $PUBLIC_URL --routing tree --noTLS"]
CMD []
7 changes: 7 additions & 0 deletions Dockerfiles/Dockerfile.frontend
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,12 @@ ENV REACT_APP_NOMOCK=on
WORKDIR /web/frontend
COPY ../web/frontend .
RUN npm install
ARG REACT_APP_VERSION=unknown
ARG REACT_APP_BUILD=unknown
ARG REACT_APP_BUILD_TIME=after_2024_03
ENV REACT_APP_VERSION=$REACT_APP_VERSION
ENV REACT_APP_BUILD=$REACT_APP_BUILD
ENV REACT_APP_BUILD_TIME=$REACT_APP_BUILD_TIME

ENTRYPOINT ["npm"]
CMD ["start"]
96 changes: 33 additions & 63 deletions README.docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,96 +8,66 @@ The files related to the Docker environment can be found in
* `Dockerfiles/` (Dockerfiles)
* `scripts/` (helper scripts)

You also need to either create a `.env` file in the project's root
or point to another environment file using the `--env-file` flag
when running `docker compose`.
### Setup

The environment file needs to contain
It is recommended to use the `run_docker.sh` helper script for setting up and
tearing down the environment as it handles all the necessary intermediary steps
to have a working D-Voting application.

```
DELA_NODE_URL=http://172.19.44.254:8080
DATABASE_USERNAME=dvoting
DATABASE_PASSWORD=XXX # choose any PostgreSQL password
DATABASE_HOST=db
DATABASE_PORT=5432
DB_PATH=dvoting # LMDB database path
FRONT_END_URL=http://127.0.0.1:3000
BACKEND_HOST=backend
BACKEND_PORT=5000
SESSION_SECRET=XXX # choose any secret
PUBLIC_KEY=XXX # public key of pre-generated key pair
PRIVATE_KEY=XXX # private key of pre-generated key pair
PROXYPORT=8080
NODEPORT=2000 # DELA node port
```
This script needs to be executed at the project's root.

For the `PUBLIC_KEY` and `PRIVATE_KEY`, you need to run the following commands:
To set up the environment:

```bash
cd web/backend
npm ci
npm run keygen
```
./scripts/run_docker.sh
```

And then copy the two lines to the `.env` file.

There are two Docker Compose file you may use:
This will run the subcommands:

* `docker-compose/docker-compose.yml` for the preprod version, or
* `docker-compose/docker-compose.debug.yml` for the development/debugging version
- `setup` which will build the images and start the containers
- `init_dela` which will initialize the DELA network
- `local_admin` which will add local admin accounts for testing and debugging
- `local_login` which will set a local cookie that allows for interacting w/ the API via command-line
- `add_proxies` which will set up the DELA node proxies

You run
Each of these subcommands can also be run by invoking the script w/ the subcommand:

```
export COMPOSE_FILE=<path to Docker Compose file>
./scripts/run_docker.sh <subcommand>
```

The preprod version will create an environment without any debugging tools that's as close as possible to a real environment.
It is meant to be used to test the `main` branch before deploying it to production. Use the development/debugging version
for setting up your local development environment.
/!\ The `init_dela` subcommand must only be run exactly **once**.

Run
To tear down the environment:

```
docker compose build
docker compose up
./scripts/run_docker.sh teardown
```

to set up the environment.

/!\ Any subsequent `docker compose` commands must be run with `COMPOSE_FILE` being
set to the Docker Compose file that defines the current environment.

Use
This will:

```
docker compose down
```
- remove the local cookie
- stop and remove the containers and their attached volumes
- remove the images

to shut off, and
/!\ This command is meant to reset your environment. If you want to stop one or more
containers, use the appropriate `docker compose` commands (see below for using the correct `docker-compose.yml`).

```
docker compose down -v
```
### Docker environment

to delete the volumes and reset your instance.
There are two Docker Compose file you may use:

## Post-install commands
* `docker-compose/docker-compose.yml` (recommended, default in `.env.example` and `run_docker.sh`), or
* `docker-compose/docker-compose.debug.yml`, which contains some additional debugging tools

To set up the DELA network, go to `scripts/` and run
To run `docker compose` commands w/ the right `docker-compose.yml`, you need to either run

```
./init_dela.sh
export COMPOSE_FILE=<path to Docker Compose file>
```

/!\ This script uses `docker compose` as well, so make sure that the `COMPOSE_FILE` variable is
set to the right value.

To set up the permissions, run
or

```
docker compose exec backend npx cli addAdmin --sciper XXX
docker compose down && docker compose up -d
source .env
```

to add yourself as admin and clear the cached permissions.
128 changes: 128 additions & 0 deletions scripts/run_docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/bin/bash -e

# The script must be called from the root of the github tree, else it returns an error.
# This script currently only works on Linux due to differences in network management on Windows/macOS.

if [[ $(git rev-parse --show-toplevel) != $(pwd) ]]; then
echo "ERROR: This script must be started from the root of the git repo";
exit 1;
fi

if [[ ! -f .env ]]; then
cp .env.example .env
fi

source ./.env;
export COMPOSE_FILE=${COMPOSE_FILE:-./docker-compose/docker-compose.yml};


function setup() {
docker compose build;
docker compose up -d;
}

function teardown() {
rm -f cookies.txt;
docker compose down -v;
docker image rm ghcr.io/c4dt/d-voting-frontend:latest ghcr.io/c4dt/d-voting-backend:latest ghcr.io/c4dt/d-voting-dela:latest;
}

function init_dela() {
LEADER=dela-worker-0;
echo "$LEADER is the initial leader node";

echo "add nodes to the chain";
MEMBERS=""
for node in $(seq 0 3); do
MEMBERS="$MEMBERS --member $(docker compose exec dela-worker-$node /bin/bash -c 'LLVL=error dvoting --config /data/node ordering export')";
done
docker compose exec "$LEADER" dvoting --config /data/node ordering setup $MEMBERS;

echo "authorize signers to handle access contract on each node";
for signer in $(seq 0 3); do
IDENTITY=$(docker compose exec "dela-worker-$signer" crypto bls signer read --path /data/node/private.key --format BASE64_PUBKEY);
for node in $(seq 0 3); do
docker compose exec "dela-worker-$node" dvoting --config /data/node access add --identity "$IDENTITY";
done
done

echo "update the access contract";
for node in $(seq 0 3); do
IDENTITY=$(docker compose exec dela-worker-"$node" crypto bls signer read --path /data/node/private.key --format BASE64_PUBKEY);
docker compose exec "$LEADER" dvoting --config /data/node pool add\
--key /data/node/private.key\
--args go.dedis.ch/dela.ContractArg\
--args go.dedis.ch/dela.Access\
--args access:grant_id\
--args 45564f54\
--args access:grant_contract\
--args go.dedis.ch/dela.Evoting \
--args access:grant_command\
--args all\
--args access:identity\
--args $IDENTITY\
--args access:command\
--args GRANT
done
}


function local_admin() {
echo "adding local user $REACT_APP_SCIPER_ADMIN to admins";
docker compose exec backend npx cli addAdmin --sciper "$REACT_APP_SCIPER_ADMIN";
docker compose exec backend npx cli addAdmin --sciper 987654;
docker compose restart backend;
}


function local_login() {
if ! [ -f cookies.txt ]; then
echo "getting dummy login cookie";
curl -k "$FRONT_END_URL/api/get_dev_login/$REACT_APP_SCIPER_ADMIN" -c cookies.txt -o /dev/null -s;
fi
}

function add_proxies() {

echo "adding proxies";

for node in $(seq 0 3); do
echo "adding proxy for node dela-worker-$node";
curl -sk "$FRONT_END_URL/api/proxies/" -X POST -H 'Content-Type: application/json' -b cookies.txt --data "{\"NodeAddr\":\"grpc://dela-worker-$node:$NODEPORT\",\"Proxy\":\"http://172.19.44.$((254 - node)):$PROXYPORT\"}";
done
}

case "$1" in

setup)
setup;
;;

init_dela)
init_dela;
;;

teardown)
teardown;
exit
;;

local_admin)
local_admin;
;;

add_proxies)
local_login;
add_proxies;
;;

*)
setup;
sleep 16; # give DELA nodes time to start up
init_dela;
local_admin;
sleep 8; # give backend time to restart
local_login;
add_proxies;
;;
esac

0 comments on commit 4b61aa4

Please sign in to comment.