Skip to content

Commit

Permalink
Merge pull request #5 from maximumadmin/docker-and-other-improvements
Browse files Browse the repository at this point in the history
Docker and other improvements
  • Loading branch information
maximumadmin authored Mar 21, 2021
2 parents 5ebbc60 + b3e65be commit 37ab7c2
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 53 deletions.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*
!extra/
!scripts/
!src/
!go.mod
!go.sum
!LICENSE
!Makefile
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ jobs:
go-version: 1.16
- name: Test
run: make test
# Keep in mind that tags should only be in one of the following formats
# vVERSION or vVERSION-RELEASE e.g. v0.8.5 or v0.8.5-1
- name: Set environment variables
run: echo "CURRENT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
# run: |-
Expand Down
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM golang:1.16.2-buster

RUN apt-get update &&\
apt-get install -y python3 python3-yaml &&\
apt-get clean &&\
rm -rf /var/lib/apt/lists/*

WORKDIR /go/src/app

COPY ["go.mod", "go.sum", "./"]
RUN go mod download

COPY . .

ARG CURRENT_TAG
ENV CURRENT_TAG=${CURRENT_TAG}
ARG COMMIT_DATE
ENV COMMIT_DATE=${COMMIT_DATE}

RUN python3 scripts/build.py
85 changes: 70 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ default:
set -e ;\
os_release_id=$$(grep -E '^ID=' /etc/os-release | sed 's/ID=//' || true) ;\
if [ "$$os_release_id" = "arch" ]; then \
make --no-print-directory release-dynamic ;\
make --no-print-directory release type=dynamic ;\
else \
make --no-print-directory release-static ;\
make --no-print-directory release type=static ;\
fi ;\
}

start:
go run $(GO_FILE)

clean:
go clean
go clean || true
rm -rf dist/*
rm -f "$(OUT_FILE)"

Expand All @@ -31,37 +31,52 @@ build:
go build -v -o $(OUT_FILE) $(GO_FILE)
@ls -lh "$(OUT_FILE)"

release:
@{\
set -e ;\
if [ "$(type)" != "static" ] && [ "$(type)" != "dynamic" ]; then \
echo "The type parameter must be \"static\" or \"dynamic\"" ;\
exit 1 ;\
fi ;\
echo "Building $(type) binary (GOARCH: $(GOARCH) GOARM: $(GOARM))..." ;\
if [ -z "$${skip_clean}" ]; then make --no-print-directory clean; fi ;\
export VERSION_FLAGS="-X main.Version=$$(make --no-print-directory version) -X main.CommitDate=$$(make --no-print-directory commit-date)" ;\
case "$(type)" in \
static) \
make --no-print-directory release-static ;\
;;\
dynamic) \
make --no-print-directory release-dynamic ;\
;;\
esac ;\
}
@make --no-print-directory postbuild

# Build statically linked production binary
release-static:
@echo "Building static binary (GOARCH: $(GOARCH) GOARM: $(GOARM))..."
@{\
set -e ;\
if [ -z "$${skip_clean}" ]; then make --no-print-directory clean; fi ;\
export GOFLAGS="-a -trimpath -ldflags=-w -ldflags=-s" ;\
args=(-a -trimpath -ldflags "-w -s $${VERSION_FLAGS}") ;\
if [ "$${GOARCH}" != "arm" ]; then \
export GOFLAGS="$${GOFLAGS} -buildmode=pie" ;\
args+=("-buildmode=pie") ;\
fi ;\
CGO_ENABLED=0 go build -o "$(OUT_FILE)" $(GO_FILE) ;\
CGO_ENABLED=0 go build "$${args[@]}" -o "$(OUT_FILE)" $(GO_FILE) ;\
}
@make --no-print-directory postbuild

# Build dinamically linked production binary
release-dynamic:
@echo "Building dynamic binary (GOARCH: $(GOARCH) GOARM: $(GOARM))..."
@{\
set -e ;\
if [ -z "$${skip_clean}" ]; then make --no-print-directory clean; fi ;\
export CGO_CPPFLAGS="$${CPPFLAGS}" ;\
export CGO_CFLAGS="$${CFLAGS}" ;\
export CGO_CXXFLAGS="$${CXXFLAGS}" ;\
export CGO_LDFLAGS="$${LDFLAGS}" ;\
export GOFLAGS="-a -trimpath -ldflags=-linkmode=external -ldflags=-w -ldflags=-s" ;\
args=(-a -trimpath -ldflags "-linkmode external -w -s $${VERSION_FLAGS}") ;\
if [ "$${GOARCH}" != "arm" ]; then \
export GOFLAGS="$${GOFLAGS} -buildmode=pie" ;\
args+=("-buildmode=pie") ;\
fi ;\
go build -o "$(OUT_FILE)" $(GO_FILE) ;\
go build "$${args[@]}" -o "$(OUT_FILE)" $(GO_FILE) ;\
}
@make --no-print-directory postbuild

postbuild:
@{\
Expand All @@ -87,6 +102,46 @@ postbuild:
}
@ls -lh "$(OUT_FILE)"*

docker:
@{\
set -e ;\
image_name=$(MODULE)_$$(openssl rand -hex 8) ;\
container_name=$(MODULE)_$$(openssl rand -hex 8) ;\
docker build \
--build-arg "CURRENT_TAG=$${CURRENT_TAG}" \
--build-arg "COMMIT_DATE=$$(make --no-print-directory commit-date)" \
--tag $${image_name} . ;\
docker run -d --rm --name $${container_name} --entrypoint tail $${image_name} -f /dev/null ;\
make --no-print-directory clean ;\
docker cp $${container_name}:/go/src/app/dist . ;\
docker stop -t 0 $${container_name} ;\
docker rmi --no-prune $${image_name} ;\
}

# Print the value of the VERSION variable if available, otherwise get version
# based on the latest git tag
version:
@{\
set -e ;\
if [ ! -z "$$VERSION" ]; then \
echo "$$VERSION" ;\
exit 0 ;\
fi ;\
git describe --tags | sed -r 's/^v([0-9]+\.[0-9]+\.[0-9]+).*/\1/' ;\
}

# Print the value of the COMMIT_DATE variable if available, otherwise get commit
# date from the last git commit
commit-date:
@{\
set -e ;\
if [ ! -z "$$COMMIT_DATE" ]; then \
echo "$$COMMIT_DATE" ;\
exit 0 ;\
fi ;\
git log -1 --no-merges --format=%cI ;\
}

# Run unit tests on all packages
test:
go test -v ./src/...
Expand Down
48 changes: 27 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Automatically setup swap on zram ✨

## Reasons to swap on zram
## Why swap on zram?

* Significantly improves system responsiveness, especially when swap is under pressure.
* More secure, user data leaks into swap are on volatile media.
Expand All @@ -11,13 +11,6 @@ Automatically setup swap on zram ✨

See also https://fedoraproject.org/wiki/Changes/SwapOnZRAM#Benefit_to_Fedora

## Compiling

* Install `go`, this depends on the distribution you are using e.g. for Ubuntu the command should be `sudo apt-get install golang`.
* Run `make release` to make a x86_64 build, to make an ARM build (i.e. for the Raspberry Pi) run `GOOS=linux GOARCH=arm GOARM=7 make release`
* A new executable called `zramd.bin` will be created under the `dist/` directory, now you can uninstall `go` if you like.
* Optionally on distributions using systemd, you can install `zramd` by just running `make install`, see below for additional installation methods.

## Installation

### Install on Arch Linux from the AUR
Expand All @@ -28,20 +21,17 @@ See also https://fedoraproject.org/wiki/Changes/SwapOnZRAM#Benefit_to_Fedora
sudo systemctl enable --now zramd
```

### Manual installation on any distribution with systemd
### Install on Ubuntu / Debian / Raspberry Pi OS

* Copy the `zramd` binary to `/usr/local/bin`.
* Copy the `extra/zramd.service` file to `/etc/systemd/system`.
* Reload and start the service:
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now zramd
```
* Head to the releases section and download the `.deb` file corresponding to your system architecture
* Install using `sudo dpkg -i DEB_FILE`

### Manual installation on any distribution without systemd

* Head to the releases section and download the `.tar.gz` file corresponding to your system architecture
* Extract the downloaded file e.g. `tar xf TAR_FILE`
* Copy the `zramd` binary to `/usr/local/bin`.
* Depending on your init system there are various ways to set it up to autostart, if you are using Raspberry Pi OS, you can simply add a line to `/etc/rc.local` e.g.
* There are various ways to setup autostart depending on your init system, for example you can add a line to `/etc/rc.local` e.g.
```bash
/usr/local/bin/zramd start
```
Expand All @@ -50,9 +40,10 @@ See also https://fedoraproject.org/wiki/Changes/SwapOnZRAM#Benefit_to_Fedora

* zramd --help
```
Usage: zramd <command> [<args>]
Usage: zramd [--version] <command> [<args>]

Options:
--version print program version
--help, -h display this help and exit

Commands:
Expand All @@ -78,22 +69,37 @@ See also https://fedoraproject.org/wiki/Changes/SwapOnZRAM#Benefit_to_Fedora
--help, -h display this help and exit
```

## Compilation

### With Docker

* Choose a valid git tag and run the `make docker` command e.g.
```bash
CURRENT_TAG=v0.8.5 make docker
```

### Manual Compilation

* Install `go`, this depends on the distribution you are using e.g. for Ubuntu the command should be `sudo apt-get install golang`.
* Run `make release` to make a x86_64 build, to make an ARM build (i.e. for the Raspberry Pi) run `GOOS=linux GOARCH=arm GOARM=7 make release`
* A new executable called `zramd.bin` will be created under the `dist/` directory, now you can uninstall `go` if you like.

## Configuration

### With systemd

The default configuration file is located at `/etc/default/zramd`, just edit the variables as you like and restart the `zramd` service i.e. `sudo systemctl restart zramd`.
* The default configuration file is located at `/etc/default/zramd`, just edit the variables as you like and restart the `zramd` service i.e. `sudo systemctl restart zramd`

### Without systemd

Just change the arguments as you like, e.g. `zramd start --max-size 1024` or `zramd start --percent 0.5 --priority 0`.
* Just change the arguments as you like, e.g. `zramd start --max-size 1024` or `zramd start --percent 0.5 --priority 0`

## Troubleshooting

* **modprobe: FATAL: Module zram not found in directory /lib/modules/...**
It can happen if you try to start the `zramd` service after a kernel upgrade, you just need to restart your computer.
* **error: swapon: /dev/zramX: swapon failed: Operation not permitted**
First make sure that you are running as root (or at least that you have the required capabilities), also keep in mind that Linux only supports up to 32 swap devices (although it can start throwing the error from above when using a high value like 24 🤷‍♂).
First make sure that you are running as root (or at least that you have the required capabilities), also keep in mind that Linux only supports up to 32 swap devices (although it can start throwing the error from above when using a high value like 24).

## Notes

Expand Down
6 changes: 4 additions & 2 deletions scripts/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ def clean() -> int:
return subprocess.run(['make', 'clean'], env=os.environ).returncode

def main() -> int:
if (ret := clean()) != 0:
ret = clean()
if ret != 0:
return ret

# Build all targets sequentially, building in parallel will have minimal or no
# benefit and would make logging messy
for target in TARGETS:
if (ret := build(*target)) != 0:
ret = build(*target)
if ret != 0:
return ret

# Finally write the used architectures so we can use them at later steps
Expand Down
29 changes: 16 additions & 13 deletions scripts/mkdeb.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
def print_error(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)

def read_config(file: str) -> str:
def read_config(file: str) -> dict:
with open(file, 'r') as f:
return yaml.safe_load(f)

Expand All @@ -30,7 +30,8 @@ def dir_size(path: str) -> int:
def parse_env(text: str, env: dict) -> str:
result = text
for expr, name in ENV_RE.findall(text):
if (env_val := env.get(name)) is not None:
env_val = env.get(name)
if env_val is not None:
result = result.replace(expr, env_val)
return result

Expand Down Expand Up @@ -79,10 +80,12 @@ def make_deb(prefix: str, args: List[str]) -> int:
return subprocess.run(final_args).returncode

def main() -> int:
if not (config_file := os.environ.get('CONFIG_FILE')):
config_file = os.environ.get('CONFIG_FILE')
if not config_file:
print_error('the CONFIG_FILE variable is not set')
return 1
if not (prefix := os.environ.get('PREFIX')):
prefix = os.environ.get('PREFIX')
if not prefix:
print_error('the PREFIX variable is not set')
return 1

Expand All @@ -91,17 +94,15 @@ def main() -> int:
exist_ok=True
)

config: dict = read_config(config_file)
config = read_config(config_file)

install_cmd = (
cmd
if (cmd := config.get('build', {}).get('install', {}).get('cmd'))
else ['make', 'install']
)
cmd = config.get('build', {}).get('install', {}).get('cmd')
install_cmd = cmd if cmd else ['make', 'install']
install_env = config.get('build', {}).get('install', {}).get('env', {})
for key, val in install_env.items():
install_env[key] = parse_env(val, os.environ)
if (ret := subprocess.run(install_cmd, env=install_env).returncode) != 0:
ret = subprocess.run(install_cmd, env=install_env).returncode
if ret != 0:
return ret

env = {
Expand All @@ -119,10 +120,12 @@ def main() -> int:
write_md5sums(prefix)

args = config.get('build', {}).get('args', [])
if (ret := make_deb(prefix, args)) != 0:
ret = make_deb(prefix, args)
if ret != 0:
return ret

if (target_name := config.get('build', {}).get('rename')):
target_name = config.get('build', {}).get('rename')
if target_name:
dir_name = os.path.dirname(prefix)
final_name = parse_env(target_name, env)
os.rename(f"{prefix}.deb", os.path.join(dir_name, final_name))
Expand Down
Loading

0 comments on commit 37ab7c2

Please sign in to comment.