diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..b52edd4f47 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +_build +deps +apps/block_scout_web/assets/node_modules +apps/explorer/node_modules +test +.git +.circleci +logs +apps/*/test diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000..9c1a4809e2 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,39 @@ +FROM bitwalker/alpine-elixir-phoenix:latest + +RUN apk --no-cache --update add automake libtool inotify-tools autoconf + +EXPOSE 4000 + +ENV PORT=4000 \ + MIX_ENV="prod" \ + SECRET_KEY_BASE="RMgI4C1HSkxsEjdhtGMfwAHfyT6CKWXOgzCboJflfSm4jeAlic52io05KB6mqzc5" + +# Cache elixir deps +ADD mix.exs mix.lock ./ +ADD apps/block_scout_web/mix.exs ./apps/block_scout_web/ +ADD apps/explorer/mix.exs ./apps/explorer/ +ADD apps/ethereum_jsonrpc/mix.exs ./apps/ethereum_jsonrpc/ +ADD apps/indexer/mix.exs ./apps/indexer/ + +RUN mix do deps.get, deps.compile + +ADD . . + +# Run forderground build and phoenix digest +RUN mix compile + +# Add blockscout npm deps +RUN cd apps/block_scout_web/assets/ && \ + npm install && \ + npm run deploy && \ + cd - + +RUN cd apps/explorer/ && \ + npm install && \ + cd - + +# RUN mix do ecto.drop --force, ecto.create, ecto.migrate + +# USER default + +# CMD ["mix", "phx.server"] diff --git a/docker/Makefile b/docker/Makefile new file mode 100644 index 0000000000..9e37f5e821 --- /dev/null +++ b/docker/Makefile @@ -0,0 +1,101 @@ +SYSTEM = $(shell uname -s) +HOST = host.docker.internal +DOCKER_IMAGE = blockscout_prod +PG_CONTAINER_NAME = postgres +PG_CONTAINER_IMAGE = postgres:10.4 +THIS_FILE = $(lastword $(MAKEFILE_LIST)) + +ifeq ($(SYSTEM), Linux) + HOST=localhost +endif + +DB_URL = postgresql://postgres:@$(HOST):5432/explorer?ssl=false +BLOCKSCOUT_CONTAINNER_PARAMS = -e 'MIX_ENV=prod' \ + -e 'DATABASE_URL=$(DB_URL)' +ifeq ($(SYSTEM), Linux) + BLOCKSCOUT_CONTAINNER_PARAMS += --network=host +endif +ifdef ETHEREUM_JSONRPC_VARIANT + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_VARIANT=$(ETHEREUM_JSONRPC_VARIANT)' +endif +ifdef ETHEREUM_JSONRPC_HTTP_URL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_HTTP_URL=$(ETHEREUM_JSONRPC_HTTP_URL)' +endif +ifdef ETHEREUM_JSONRPC_WS_URL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_WS_URL=$(ETHEREUM_JSONRPC_WS_URL)' +endif +ifdef ETHEREUM_JSONRPC_TRACE_URL + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'ETHEREUM_JSONRPC_TRACE_URL=$(ETHEREUM_JSONRPC_TRACE_URL)' +endif +ifdef COIN + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'COIN=$(COIN)' +endif +ifdef LOGO + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'LOGO=$(LOGO)' +endif +ifdef NETWORK + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK=$(NETWORK)' +endif +ifdef SUBNETWORK + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'SUBNETWORK=$(SUBNETWORK)' +endif +ifdef NETWORK_ICON + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_ICON=$(NETWORK_ICON)' +endif +ifdef NETWORK_PATH + BLOCKSCOUT_CONTAINNER_PARAMS += -e 'NETWORK_PATH=$(NETWORK_PATH)' +endif + +HAS_BLOCKSCOUT_IMAGE := $(shell docker images | grep ${DOCKER_IMAGE}) +build: + @echo "==> Checking for blockscout image $(DOCKER_IMAGE)" +ifdef HAS_BLOCKSCOUT_IMAGE + @echo "==> Image exist. Using $(DOCKER_IMAGE)" +else + @echo "==> No image found trying to build one..." + @docker build -f ./Dockerfile -t $(DOCKER_IMAGE) ../ +endif + +migrate: build postgres + @echo "==> Running migrations" + @docker run --rm \ + $(BLOCKSCOUT_CONTAINNER_PARAMS) \ + $(DOCKER_IMAGE) /bin/sh -c "echo $$MIX_ENV && mix do ecto.drop --force, ecto.create, ecto.migrate" + + +PG_EXIST := $(shell docker ps -a | grep ${PG_CONTAINER_NAME}) +PG_STARTED := $(shell docker ps | grep ${PG_CONTAINER_NAME}) +postgres: +ifdef PG_EXIST + @echo "==> Checking PostrgeSQL container" +ifdef PG_STARTED + @echo "==> PostgreSQL Already started" +else + @echo "==> Starting PostgreSQL container" + @docker start $(PG_CONTAINER_NAME) +endif +else + @echo "==> Creating new PostgreSQL container" + @docker run -d --name $(PG_CONTAINER_NAME) \ + -e POSTGRES_PASSWORD="" \ + -e POSTGRES_USER="postgres" \ + -p 5432:5432 \ + $(PG_CONTAINER_IMAGE) + @sleep 1 + @$(MAKE) -f $(THIS_FILE) migrate +endif + +start: build postgres + @echo "==> Starting blockscout" + @docker run --rm \ + $(BLOCKSCOUT_CONTAINNER_PARAMS) \ + -p 4000:4000 \ + $(DOCKER_IMAGE) /bin/sh -c "mix phx.server" + +run: start + +.PHONY: build \ + migrate \ + start \ + postgres \ + run diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000000..17e142c27f --- /dev/null +++ b/docker/README.md @@ -0,0 +1,77 @@ +# BlockScout Docker integration + +For now this integration is not production ready. It made only for local usage only ! + +## How to use ? +First of all blockscout requires `PostgreSQL` server for working. +It will be provided by starting script (new docker image will be created named `postgres`) + +**Starting command** +`make start` - will set everything up and start blockscout in container. +To connect it to your local environment you will have to configure it using [env variables](#env-variables) + +Exmaple connecting to local `ganache` instance running on port `2000` on Mac/Windows: +```bash +COIN=DAI \ +ETHEREUM_JSONRPC_VARIANT=ganache \ +ETHEREUM_JSONRPC_HTTP_URL=http://host.docker.internal:2000 \ +ETHEREUM_JSONRPC_WEB_SOCKET_URL=ws://host.docker.internal:2000 \ +make start +``` + +Blockscout will be available on `localhost:4000` + +**Note** +On mac/Windows Docker provides with a special URL `host.docker.internal` that will be available into container and routed to your local machine. +On Linux docker is starting using `--network=host` and all services should be available on `localhost` + +### Migrations + +By default `Makefile` will do migrations for you on `PostgreSQL` creation. +But you could run migrations manualy using `make migrate` command. + +**WARNING** Migrations will clean up your local database ! + +## Env variables + +BlockScout support 3 different JSON RPC Variants. +Vriant could be configured using `ETHEREUM_JSONRPC_VARIANT` environment variable. + +Example: +```bash +ETHEREUM_JSONRPC_VARIANT=ganache make start +``` + +Available options are: + + * `parity` - Parity JSON RPC (**Default one**) + * `geth` - Geth JSON RPC + * `ganache` - Ganache JSON RPC + + +| Variable | Description | Default value | +| -------- | ----------- | ------------- | +| `ETHEREUM_JSONRPC_VARIANT` | Variant of your JSON RPC service: `parity`, `geth` or `ganache` | `parity` | +| `ETHEREUM_JSONRPC_HTTP_URL` | HTTP JSON RPC URL Only for `geth` or `ganache` variant | Different per JSONRPC variant | +| `ETHEREUM_JSONRPC_WS_URL` | WS JSON RPC url | Different per JSONRPC variant | +| `ETHEREUM_JSONRPC_TRACE_URL` | Trace URL **Only for `parity` variant** | `https://sokol-trace.poa.network` | +| `COIN` | Default Coin | `POA` | +| `LOGO` | Coin logo | Empty | +| `NETWORK` | Network | Empty | +| `SUBNETWORK` | Subnetwork | Empty | +| `NETWORK_ICON` | Network icon | Empty | +| `NETWORK_PATH` | Network path | `/` | + + +`ETHEREUM_JSONRPC_HTTP_URL` default values: + + * For `parity` - `https://sokol.poa.network` + * For `geth` - `https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY` + * For `ganache` - `http://localhost:7545` + +`ETHEREUM_JSONRPC_WS_URL` default values: + + * For `parity` - `wss://sokol-ws.poa.network/ws` + * For `geth` - `wss://mainnet.infura.io/8lTvJTKmHPCHazkneJsY/ws` + * For `ganache` - `ws://localhost:7545` +