Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.14.5 node for debian:bookworm-slim #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions 1.14.5/amd64-bookworm-slim/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
FROM debian:bookworm-slim AS verify

WORKDIR /verify

# Release specification
ARG RLS_VERSION=1.14.5
ARG RLS_ARCH=x86_64
ARG RLS_OS=linux
ARG RLS_LIB=gnu

ENV RLS_FILE_NAME=dogecoin-${RLS_VERSION}-${RLS_ARCH}-${RLS_OS}-${RLS_LIB}.tar.gz

ENV SIG_PATH=${RLS_VERSION}-${RLS_OS}
ENV DESCRIPTOR_PATH=contrib/gitian-descriptors/gitian-${RLS_OS}.yml
ENV PUBKEY_PATH=contrib/gitian-keys

ENV REPO_GITIAN_BUILDER=https://github.com/devrandom/gitian-builder.git
ENV REPO_GITIAN_SIGS=https://github.com/dogecoin/gitian.sigs.git
ENV REPO_DOGECOIN_CORE=https://github.com/dogecoin/dogecoin.git


# install system requirements
RUN apt update && apt install -y \
wget \
git \
ruby \
gpg \
&& rm -rf /var/lib/apt/lists/*

# fetch tools and setup signers
RUN git clone ${REPO_GITIAN_BUILDER} gitian && \
git clone ${REPO_GITIAN_SIGS} sigs && \
git clone -b v${RLS_VERSION} ${REPO_DOGECOIN_CORE} dogecoin && \
find dogecoin/${PUBKEY_PATH} -name "*.pgp" |xargs -n 1 gpg --import

# download release binary and verify against random signer
RUN wget https://github.com/dogecoin/dogecoin/releases/download/v${RLS_VERSION}/${RLS_FILE_NAME} && \
gitian/bin/gverify --no-markup -d sigs -r ${SIG_PATH} \
dogecoin/${DESCRIPTOR_PATH} | grep OK | \
shuf -n 1 | sed s/:.*// > random_signer.txt && \
grep ${RLS_FILE_NAME} sigs/${SIG_PATH}/$(cat random_signer.txt)/*assert | shasum -c && \
mv ${RLS_FILE_NAME} dogecoin.tar.gz

FROM debian:bookworm-slim AS final

ENV USER=dogecoin
ENV DATADIR=/${USER}/.dogecoin

# Root configuration to mimic user
ENV HOME=/${USER}

RUN useradd ${USER} --home-dir ${HOME}

# Dependencies install
RUN apt update && apt install -y \
python3 \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /tmp

# Copy the downloaded binary from the verify stage
COPY --from=verify /verify/dogecoin.tar.gz ./

# Move downloaded binaries and man pages in the container system.
# Setuid on binaries with $USER rights, to limit root usage.
RUN tar -xvf dogecoin.tar.gz --strip-components=1 && \
cp share/man/man1/*.1 /usr/share/man/man1 && \
cp bin/dogecoin* /usr/local/bin && \
chown ${USER}:${USER} /usr/local/bin/dogecoin* && \
chmod 4555 /usr/local/bin/dogecoin* && \
rm -rf *

COPY docker-entrypoint.py /usr/local/bin/docker-entrypoint

WORKDIR ${HOME}

# P2P network (mainnet, testnet & regnet respectively)
EXPOSE 22556 44556 18444

# RPC interface (mainnet, testnet & regnet respectively)
EXPOSE 22555 44555 18332

VOLUME ["/dogecoin/.dogecoin"]

ENTRYPOINT ["docker-entrypoint"]
141 changes: 141 additions & 0 deletions 1.14.5/amd64-bookworm-slim/docker-entrypoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#!/usr/bin/env python3

import argparse
import os
import pwd
import shutil
import sys
import subprocess
import re

def container_executable():
"""
Get the executable used in the docker command, or
use dogecoind by default.
"""
dogecoin_executables = [
"dogecoind",
"dogecoin-qt",
"dogecoin-cli",
"dogecoin-tx",
]

executable = "dogecoind"
if len(sys.argv) >= 2 and sys.argv[1] in dogecoin_executables:
executable = sys.argv.pop(1)

return executable

def characters_cleaner(raw_option):
"""
Remove a selection of characters for each extracted option of
the executable man page.
"""
char_to_remove = ["\\", "="]
for char in char_to_remove:
raw_option = raw_option.replace(char, "")
return raw_option

def executable_options():
"""
Retrieve available options for container executable, using
it's raw man page.
"""
man_folder = "/usr/share/man/man1"
man_file = os.path.join(man_folder, f"{EXECUTABLE}.1")

with open(man_file, "r") as man_filestream:
man_content = man_filestream.read()

# Regex to match single option entry in man(1) page
# Option entry is near .HP and .IP man tag
option_regex = r".HP\n\\fB\\-(.*)=?\\fR"
option_list = re.findall(option_regex, man_content)

# Remove few unexpected characters from man page
cleaned_option = map(characters_cleaner, option_list)
return list(cleaned_option)

def create_datadir():
"""
Create data directory used by dogecoin daemon.

Create manually the directory while root at container creation,
root rights needed to create folder with host volume.
"""
#Try to get datadir from argv
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("-datadir", "--datadir")
argv, _ = parser.parse_known_args()

#Try to get datadir from environment
datadir = argv.datadir or os.environ.get("DATADIR")

os.makedirs(datadir, exist_ok=True)

user = os.environ["USER"]
subprocess.run(["chown", "-R", f"{user}:{user}", datadir])

def convert_env():
"""
Convert existing environment variables into command line arguments.

Options from executable man pages are searched in the environment,
converting options in upper case and convert "-" to "_".

Exemple:
-rpcuser is RPCUSER
-help-debug is HELP_DEBUG

Environment variables can be used with an empty value if the
corresponding option do not expect a value.
"""
dogecoind_options = executable_options()
option_to_env = lambda opt_value : opt_value.upper().replace("-", "_")

cli_arguments = []
for option in dogecoind_options:
env_option = os.environ.get(option_to_env(option))

if env_option is not None:
cli_option = "-" + option
cli_option += "=" + env_option if env_option else ""
cli_arguments.append(cli_option)

return cli_arguments

def run_executable(executable_args):
"""
Run selected dogecoin executable with arguments from environment and
command line. Switch manually from root rights needed at startup
to unprivileged user.

Manually execve + setuid/setgid to run process as pid 1,
to manage a single process in a container & more predictive
signal handling.
"""
#Prepare execve(2) arguments
if EXECUTABLE in ["dogecoind", "dogecoin-qt"]:
executable_args.append("-printtoconsole")

dogecoin_executable = shutil.which(EXECUTABLE)
execve_args = [dogecoin_executable] + executable_args

#Switch process from root to user.
#Equivalent to use gosu or su-exec
user_info = pwd.getpwnam(os.environ['USER'])
os.setgid(user_info.pw_gid)
os.setuid(user_info.pw_uid)

#Run process and remove environment by security.
os.execve(dogecoin_executable, execve_args, {})

if __name__ == "__main__":
EXECUTABLE = container_executable()

create_datadir()

EXECUTABLE_ARGS = convert_env()
EXECUTABLE_ARGS += sys.argv[1:]

run_executable(EXECUTABLE_ARGS)