0

I am working on dockerfile for ethereum chain deployment. I finished dockerfile with hardcoded parameters, but when I reference this parameters as environment variables some unclear issues have been rose.

Here is a Dockerfile:

FROM ethereum/client-go:v1.10.1

COPY ./chain/accounts/swap.ethash.genesis.json /tmp

COPY ./chain/accounts/boot.key /tmp

RUN mkdir -p /tmp/keystore

COPY ./chain/accounts/keystore/${NODE_ACCOUNT_PWD_FILENAME} /tmp/keystore

RUN geth --datadir /tmp init /tmp/swap.ethash.genesis.json \
    && rm -f ~/.ethereum/geth/nodekey 

COPY ./test-pwd.sh /tmp 
RUN chmod +x ./tmp/test-pwd.sh && ./tmp/test-pwd.sh

RUN geth --unlock 0x367103555b34Eb9a46D92833e7293D540bFd7143 --password /tmp/pwd.txt --keystore /tmp/keystore

ENTRYPOINT ["geth"]

I would like to avoid hardcoded parameters and put them into .env file which is referenced under the docker compose:

version: '3.8'

services:
  geth-bootnode:
    hostname: geth-bootnode
    env_file:
      - .env
    image: geth-client
    build:
      context: .
      args:
        - ACCOUNT_PASSWORD=${ACCOUNT_PASSWORD}
        - NODE_ACCOUNT_PWD_FILENAME=${NODE_1_ACCOUNT_PWD_FILENAME}
        - NODE_ACCOUNT_PWD=${NODE_1_ACCOUNT_PWD}
        - NODE_ACCOUNT=${NODE_1_ACCOUNT}
    command:
      --nodekeyhex="c26d705bd5933bc2be72813f1b74f140aa6b3726d2a71a43b163a5c084e9dcb4"
      --nodiscover
      --ipcdisable
      --networkid=${NETWORK_ID}
      --netrestrict="172.16.254.0/28"
    networks:
      priv-eth-net:
networks:
  priv-eth-net:
    driver: bridge
    ipam:
      config:
      - subnet: 172.16.254.0/28

Reference this env var, e.g. geth --unlock ${NODE_ACCOUNT}, gives an error of missed parameter:

> [9/9] RUN geth --unlock ${NODE_ACCOUNT} --password /tmp/pwd.txt --keystore /tmp/keystore:
#0 0.397 invalid command: "/tmp/pwd.txt"

Some users mentioned it should be converted into ENV variable to be available under Runtime, but it gives similar error.

Similar issue happened with ENV var for a password and this is a reason why preparation of pwd.txt was wrapped into a shell script. .env file parameters names and actual values are double checked.

In my perspective, reference variables like ${NODE_ACCOUNT} and ${NODE_PWD} should be enough; if the runtime visibility scope is an issue, then ENV node_acc=${NODE_ACCOUNT} and ENV node_pwd=${NODE_PWD} should work. However, neither any of this options doesn't give me successful account unlock and terminate container with an error. Do I miss something here?

Gleichmut
  • 5,953
  • 5
  • 24
  • 32
  • 2
    You are setting build arguments in your `docker-compose.yaml`, but you have not declared any build arguments (using `ARG`) in your `Dockerfile`. – larsks May 11 '23 at 18:16
  • [docker-compose build environment variable](https://stackoverflow.com/questions/52429984/docker-compose-build-environment-variable) discusses `ENV` vs. `ARG` a little more. However, if you build the image with a specific `NODE_1_ACCOUNT_FILENAME` value, that specific file will be "baked in" to the image; the image isn't normally rebuilt if you rerun the container with different options. A bind mount for the file in `/tmp/keystore` might be a better approach. – David Maze May 12 '23 at 01:14
  • @larsks, thank you. I missed the point then ```ENV``` vars from docker should be mirroring in a Dockerfile. ```ARG``` as entrypoint variable for ```ENV``` variables. – Gleichmut May 12 '23 at 03:29
  • @DavidMaze, in my perspective if I define ```ARG NODE_ACCOUNT``` and pass different environment variables from each service in ```docker-compose.yaml```, then image will pick up the actual value behind ```ARG```. Do you want to say it doesn't work this way? – Gleichmut May 12 '23 at 03:33
  • I'm saying, if you change those account values and then try to re-run the container stack without rebuilding the images, it will use the old values. You'll run into similar trouble if you `docker push` the images to a registry and try to run them on another system without having access to the source code. – David Maze May 12 '23 at 10:16
  • @DavidMaze, thank you, got it. Would ```docker compose up --build``` solve this issue? Launch with this flag should always rebuild images. – Gleichmut May 12 '23 at 10:46
  • 1
    In the same way you don't recompile Docker every time you run it on a different container, you shouldn't have to rebuild your image either. Rebuilding the image every time will work, but it'll be slow and hard to use in some environments. – David Maze May 12 '23 at 13:23

1 Answers1

0

The final solution would look like this:

FROM ethereum/client-go:v1.10.1

ARG NODE_ACCOUNT
ARG NODE_ACCOUNT_PWD

COPY ./chain/accounts/swap.ethash.genesis.json /tmp

COPY ./chain/accounts/boot.key /tmp

RUN mkdir -p /tmp/keystore

COPY ./chain/accounts/keystore/${NODE_ACCOUNT_PWD_FILENAME} /tmp/keystore

RUN geth --datadir /tmp init /tmp/swap.ethash.genesis.json \
    && rm -f ~/.ethereum/geth/nodekey 

RUN echo ${NODE_ACCOUNT_PWD} >> /tmp/pwd.txt

COPY ./chain/accounts/entrypoint.sh /tmp

RUN chmod +x ./tmp/entrypoint.sh

ENV NODE_ACCOUNT=${NODE_ACCOUNT}

# This way entrypoint usage would ignore OS signals sent the container. That might cause some issues
# Is it root cause of issue to unable 'geth attach <ip address>'?
ENTRYPOINT ./tmp/entrypoint.sh ${NODE_ACCOUNT} 

ENV vars from docker-compose.yaml should be mirrored in a Dockerfile. ARG serves as an entrypoint variable for ENV variables. Thank you, @larsks, for point out on this!

Gleichmut
  • 5,953
  • 5
  • 24
  • 32