Skip to content

Commit

Permalink
Merge pull request #4 from alexzhangs/develop
Browse files Browse the repository at this point in the history
improvement: multi-stage build and dns-lexicon enabled.
improvement: docker-entrypoint.sh: add domain to done files.
enhancement: docker-build-and-run.sh.
  • Loading branch information
alexzhangs authored May 24, 2024
2 parents 2a47def + a1ed927 commit abb881f
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 103 deletions.
96 changes: 72 additions & 24 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -63,46 +63,38 @@
# For more information, please refer to the project repository:
# https://github.com/alexzhangs/shadowsocks-libev-v2ray
#
FROM shadowsocks/shadowsocks-libev:edge

# Set work directory
WORKDIR /shadowsocks-libev-v2ray
# To enable proxy at build time, use:
# docker build --build-arg https_proxy=http://host.docker.internal:$PROXY_HTTP_PORT_ON_HOST ...
ARG http_proxy https_proxy all_proxy

# Copy the current directory contents at local into the container
COPY . .

RUN chmod +x docker-entrypoint.sh
### First stage: build environment
FROM alpine as builder

# Instal file, git, curl, and openssl
RUN apk add file git curl openssl

# Install acme.sh
RUN curl -sL https://get.acme.sh | sh

# Set the PATH for acme.sh
ENV PATH=$PATH:/root/.acme.sh
# Instal file, git, curl
RUN apk add file git curl

# Verify that acme.sh is installed
RUN acme.sh --version
# v2ray-plugin requires Go 1.16
ENV GO_VERSION=1.16.10

# Install Go 1.16 (v2ray-plugin requires Go 1.16)
# Install Go
RUN <<EOF
set -ex
ARCH=$(uname -m)
case ${ARCH} in
x86_64)
GO_BINARY_URL="https://dl.google.com/go/go1.16.10.linux-amd64.tar.gz"
GO_BINARY_URL="https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz"
;;
aarch64)
GO_BINARY_URL="https://dl.google.com/go/go1.16.10.linux-arm64.tar.gz"
GO_BINARY_URL="https://dl.google.com/go/go${GO_VERSION}.linux-arm64.tar.gz"
;;
*)
echo "${ARCH}: Unsupported architecture"
exit 1
;;
esac
curl -LO ${GO_BINARY_URL}
tar -C /usr/local -xzf go1.16.10.linux-*.tar.gz
tar -C /usr/local -xzf go*.tar.gz

# Workaround to fix error: go: not found
# Use `file $(which go)` to debug the missing library
Expand All @@ -112,7 +104,7 @@ RUN <<EOF
ln -s /lib/ld-musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
;;
aarch64)
ln -s /lib/ld-musl-aarch64.so.1 /lib/ld-linux-aarch64.so.1
ln -s ld-musl-aarch64.so.1 /lib/ld-linux-aarch64.so.1
;;
esac
EOF
Expand All @@ -133,8 +125,64 @@ EOF
# Verify that v2ray-plugin is installed
RUN v2ray-plugin -version

# Install Bash
RUN apk add bash

### Second stage: final image
FROM shadowsocks/shadowsocks-libev:edge

# Copy the v2ray-plugin binary from the builder stage
COPY --from=builder /usr/bin/v2ray-plugin /usr/bin/v2ray-plugin

# Link the missing library
RUN <<EOF
# Workaround to fix error: v2ray-plugin: not found
# Use `file $(which v2ray-plugin)` to debug the missing library
set -ex
ARCH=$(uname -m)
case ${ARCH} in
x86_64)
mkdir /lib64
ln -s /lib/ld-musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
;;
aarch64)
ln -s ld-musl-aarch64.so.1 /lib/ld-linux-aarch64.so.1
;;
esac
EOF

# Verify that v2ray-plugin is installed
RUN v2ray-plugin -version

# Instal file, curl, openssl, bash, python3, py3-pip
RUN apk update && \
apk add file \
# used by acme.sh
curl openssl \
# used by docker-entrypoint.sh
bash \
# used by dns-lexicon and its dependencies
python3 py3-pip gcc linux-headers libc-dev python3-dev libffi-dev && \
if [[ ! -e /usr/bin/python ]]; then ln -s python3 /usr/bin/python ; fi && \
if [[ ! -e /usr/bin/pip ]]; then ln -s pip3 /usr/bin/pip ; fi

# Install dns-lexicon
RUN pip install dns-lexicon

# Install acme.sh
RUN curl -sL https://get.acme.sh | sh

# Set the PATH for acme.sh
ENV PATH=$PATH:/root/.acme.sh

# Verify that acme.sh is installed
RUN acme.sh --version

# Set work directory
WORKDIR /shadowsocks-libev-v2ray

# Copy the current directory contents at local into the container
COPY . .

RUN chmod +x docker-entrypoint.sh

# Use the entrypoint script from this repository over the one from shadowsocks/shadowsocks-libev:edge
ENTRYPOINT [ "./docker-entrypoint.sh" ]
Expand Down
46 changes: 0 additions & 46 deletions build-and-run.sh

This file was deleted.

162 changes: 162 additions & 0 deletions docker-build-and-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/usr/bin/env bash

#? Description:
#? Build the Docker images and run the containers for testing.
#?
#? Without any option, it will build the images and run the containers in the foreground.
#?
#? Usage:
#? docker-build-and-run.sh [-P] [-m MGT_PORT] [-p SS_PORTS] [-e ENCRYPT] -d DOMAIN [-N DNS] [-E DNS_ENV]
#? docker-build-and-run.sh [-h]
#?
#? Options:
#? [-P]
#?
#? Enable to fetch the env `DOCKER_BUILD_ARGS_PROXY` and pass to docker build command.
#? If the env `DOCKER_BUILD_ARGS_PROXY` is not set or empty, exit with error.
#?
#? [-m MGT_PORT]
#?
#? Specify the management port for the shadowsocks manager.
#? Default is 6001.
#?
#? [-p SS_PORTS]
#?
#? Specify the shadowsocks ports to be exposed.
#? Default is 8381-8385.
#?
#? [-e ENCRYPT]
#?
#? Specify the encryption method for shadowsocks.
#? Default is aes-256-cfb.
#?
#? -d DOMAIN
#?
#? Specify the domain for the shadowsocks server.
#?
#? [-N DNS]
#?
#? Specify the DNS provider for the DOMAIN.
#?
#? [-E DNS_ENV]
#?
#? Specify the environment variables for the DNS provider.
#?
#? [-h]
#?
#? This help.
#?
#? Environment:
#? The following environment variables are used by this script conditionally:
#?
#? - DOCKER_BUILD_ARGS_PROXY="--build-arg http_proxy=http://host.docker.internal:1086 --build-arg https_proxy=http://host.docker.internal:1086 --build-arg all_proxy=socks5://host.docker.internal:1086"
#?
#? Optional, default is unset.
#? Set the proxy for the Docker build. Please replace the proxy port with your actual port.
#?

# exit on any error
set -e -o pipefail

function usage () {
awk '/^#\?/ {sub("^[ ]*#\\?[ ]?", ""); print}' "$0" \
| awk '{gsub(/^[^ ]+.*/, "\033[1m&\033[0m"); print}'
}

function check-vars () {
declare var ret=0
for var in "$@"; do
if [[ -z ${!var} ]]; then
echo "FATAL: environment variable $var is not set or empty." >&2
(( ret++ ))
fi
done
return $ret
}

function main () {
declare proxy_flag=0 \
mgt_port=6001 ss_ports=8381-8385 encrypt=aes-256-cfb domain dns dns_env \
OPTIND OPTARG opt

while getopts Pm:p:e:d:N:E:h opt; do
case $opt in
P)
proxy_flag=1
;;
m)
mgt_port=$OPTARG
;;
p)
ss_ports=$OPTARG
;;
e)
encrypt=$OPTARG
;;
d)
domain=$OPTARG
;;
N)
dns=$OPTARG
;;
E)
dns_env=$OPTARG
;;
*)
usage
return 255
;;
esac
done

check-vars domain mgt_port ss_ports encrypt

declare build_opts=() \
run_opts=(--restart=always) \
run_env_opts=(-e V2RAY=1 -e DOMAIN="$domain" -e DNS="$dns" -e DNS_ENV="$dns_env") \
run_port_opts=(-p "$mgt_port:$mgt_port/UDP" -p "$ss_ports:$ss_ports" -p "$ss_ports:$ss_ports/UDP") \
run_cmd_opts=( ss-manager
--manager-address "0.0.0.0:$mgt_port"
--executable /usr/local/bin/ss-server -m "$encrypt" -s 0.0.0.0 -u
--plugin v2ray-plugin --plugin-opts "server;tls;host=$domain"
)

if [[ $proxy_flag -eq 1 ]]; then
check-vars DOCKER_BUILD_ARGS_PROXY
# do not quote it
# shellcheck disable=SC2206
build_opts+=($DOCKER_BUILD_ARGS_PROXY)
fi

declare image_name=alexzhangs/shadowsocks-libev-v2ray

declare script_dir
script_dir=$(dirname "$0")

declare -a BUILD_OPTS RUN_OPTS

function __build_and_run__ () {
# build the image
echo ""
echo "INFO: docker build ${BUILD_OPTS[*]}"
docker build "${BUILD_OPTS[@]}"

# run the container
echo ""
echo "INFO: docker run ${RUN_OPTS[*]}"
docker run "${RUN_OPTS[@]}" || :
}

declare image_tag image container
image_tag=dev-$(date +%Y%m%d-%H%M)
image="$image_name:$image_tag"
container="ss-libev-$image_tag"
BUILD_OPTS=( "${build_opts[@]}" -t "$image" -f "$script_dir/Dockerfile" "$script_dir" )
RUN_OPTS=( "${run_opts[@]}" "${run_env_opts[@]}" "${run_port_opts[@]}" --name "$container" "$image" "${run_cmd_opts[@]}" )

__build_and_run__
}

main "$@"

exit
Loading

0 comments on commit abb881f

Please sign in to comment.