From 258b10edc90d53c31225962dde6dcc80b0fc9ba9 Mon Sep 17 00:00:00 2001 From: Ruben ten Hove Date: Tue, 5 Jul 2022 12:39:02 -0400 Subject: [PATCH] refactor: more containerization --- .dockerignore | 7 +++++ .github/workflows/container.yml | 43 +++++++++++++++++++++++++++++ Dockerfile | 19 ++++++------- readme_template.md | 26 ++++++++++++++--- updateHostsFile.py | 49 +++++++++++++++++++++++++-------- updateHostsWindows.bat | 0 updateReadme.py | 2 +- 7 files changed, 118 insertions(+), 28 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/container.yml mode change 100644 => 100755 updateHostsFile.py mode change 100644 => 100755 updateHostsWindows.bat mode change 100644 => 100755 updateReadme.py diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..e27f1a0dc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +* +!updateHostsFile.py +!data +!alternates +!extensions +!readmeData.json +!requirements.txt diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml new file mode 100644 index 000000000..0b4e54113 --- /dev/null +++ b/.github/workflows/container.yml @@ -0,0 +1,43 @@ +# Based on https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions#publishing-a-package-using-an-action + +name: Create and publish a container image + +on: + push: + branches: + - master + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + name: Build and push container image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + - name: Build and push container image + uses: docker/build-push-action@v3 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index d71293ced..11fa72ae6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,11 @@ -# using container digest is recommended https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests -# https://cloud.google.com/architecture/using-container-images +FROM docker.io/python:3-alpine -FROM python:3@sha256:b7bfea0126f539ba570a01fb595ee84cc4e7dcac971ad83d12c848942fa52cb6 +ENV IN_CONTAINER 1 -WORKDIR /usr/src -COPY requirements.txt ./ -RUN pip install --no-cache-dir -r requirements.txt -RUN git clone --depth 1 https://github.com/StevenBlack/hosts.git -WORKDIR /usr/src/hosts +RUN apk add --no-cache git sudo -# Now you launch this with -# $ docker build ./ -# $ docker run -it (containerid) bash +COPY . /usr/src/hosts + +RUN pip install --no-cache-dir --upgrade -r /usr/src/hosts/requirements.txt + +ENV PATH $PATH:/usr/src/hosts diff --git a/readme_template.md b/readme_template.md index 52fe6a59c..8d65f71ce 100644 --- a/readme_template.md +++ b/readme_template.md @@ -72,19 +72,37 @@ You have two options to generate your own hosts file. You can do it in your own ### Option 1: Generate in a Docker container -We provide a [Dockerfile](https://github.com/StevenBlack/hosts/blob/master/Dockerfile) that you can use to create a Docker container with everything you need. +We provide a [Dockerfile](https://github.com/StevenBlack/hosts/blob/master/Dockerfile) that you can use to create a container image with everything you need. The container will contain Python 3 and all its dependency requirements, and a copy of the latest version of this repository. Build the Docker container like this: ```sh -docker build ./ +docker build --no-cache . -t stevenblack-hosts ``` -Access the terminal like this: +Then run your command as such: ```sh -docker run -it (containerid) bash +docker run --rm -it -v "${PWD}/test:/pwd" stevenblack-hosts updateHostsFile.py +``` + +> It is recommended to mount a host directory, so your changes are saved when you exit +the container. Add `-v "${PWD}:/pwd" -w /pwd` after `-it` to mount your current working +directory, and have that as current working directory in your container. + +#### Linux example + +This will replace your `/etc/hosts` and optionally add any custom hosts. + +(Optionally) First create custom hosts files as per [the instructions](#how-do-i-control-which-sources-are-unified). + +Then run the following command to have everything setup. + +```sh +docker run --pull always --rm -it -v /etc/hosts:/etc/hosts -v "${PWD}:/pwd" \ +-w /pwd ghcr.io/StevenBlack/hosts updateHostsFile.py --auto \ +--replace --extensions gambling porn ``` ### Option 2: Generate it in your own environment diff --git a/updateHostsFile.py b/updateHostsFile.py old mode 100644 new mode 100755 index fb7119443..8d60d9d90 --- a/updateHostsFile.py +++ b/updateHostsFile.py @@ -12,6 +12,7 @@ import json import locale import os import platform +from pathlib import Path import re import shutil import socket @@ -467,7 +468,7 @@ def prompt_for_move(final_file, **move_params): move_file = query_yes_no(prompt) if move_file: - move_hosts_file_into_place(final_file) + move_file = move_hosts_file_into_place(final_file) return move_file @@ -1279,17 +1280,41 @@ def move_hosts_file_into_place(final_file): filename = os.path.abspath(final_file.name) - if os.name == "posix": - print( - "Moving the file requires administrative privileges. You might need to enter your password." - ) - if subprocess.call(SUDO + ["cp", filename, "/etc/hosts"]): - print_failure("Moving the file failed.") - elif os.name == "nt": - print("Automatically moving the hosts file in place is not yet supported.") - print( - "Please move the generated file to %SystemRoot%\\system32\\drivers\\etc\\hosts" - ) + if sys.platform == "linux": + target_file = "/etc/hosts" + + if os.getenv("IN_CONTAINER"): + # It's not allowed to remove/replace a mounted /etc/hosts, so we replace the content. + # This requires running the container user as root, as is the default. + print(f"Running in container, so we will replace the content of {target_file}.") + try: + with open(target_file, "w") as target_stream: + with open(filename, "r") as source_stream: + target_stream.write(source_stream.read()) + return True + except Exception: + print_failure(f"Replacing content of {target_file} failed.") + return False + else: + print( + f"Replacing {target_file} requires root privileges. You might need to enter your password." + ) + try: + subprocess.run(SUDO + ["cp", filename, target_file], check=True) + return True + except subprocess.CalledProcessError: + print_failure(f"Replacing {target_file} failed.") + return False + elif sys.platform == "win32": + target_file = Path(os.getenv("SystemRoot")) / "system32" / "drivers" / "etc" / "hosts" + try: + with open(target_file, "w") as target_stream: + with open(filename, "r") as source_stream: + target_stream.write(source_stream.read()) + return True + except Exception: + print_failure(f"Replacing content of {target_file} failed.") + return False def flush_dns_cache(): diff --git a/updateHostsWindows.bat b/updateHostsWindows.bat old mode 100644 new mode 100755 diff --git a/updateReadme.py b/updateReadme.py old mode 100644 new mode 100755 index ce1dbeee1..cb65262d5 --- a/updateReadme.py +++ b/updateReadme.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Script by Steven Black # https://github.com/StevenBlack