Skip to content
Merged
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
59 changes: 52 additions & 7 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,66 @@ env:
DOCKER_MIRROR_REGISTRY_PASSWORD: ${{ secrets.DOCKER_MIRROR_REGISTRY_PASSWORD }}

jobs:
docker_kit:
name: 'docker-kit'
## Clash
docker_clash:
name: 'app-clash'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
source ./tool.sh && build_image docker-kit latest docker_docker_kit/Dockerfile && push_image
source ./tool.sh && build_image app-clash latest docker_app_clash/Dockerfile && push_image

## DevBox - base
qpod_base-dev:
name: 'developer,base-dev'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
source ./tool.sh && free_diskspace
build_image base-dev latest docker_devbox/Dockerfile \
--build-arg "BASE_IMG=node" \
--build-arg "ARG_PROFILE_JUPYTER=base,kernels,extensions" \
--build-arg "ARG_PROFILE_VSCODE=base"
alias_image base-dev latest developer latest && push_image dev
## DevBox - full stack
qpod_full-stack-dev:
name: 'full-stack-dev'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
source ./tool.sh && free_diskspace
build_image full-stack-dev latest docker_devbox/Dockerfile \
--build-arg "BASE_IMG=full-stack" \
--build-arg "ARG_PROFILE_JUPYTER=base,kernels,extensions" \
--build-arg "ARG_PROFILE_VSCODE=base"
push_image
## DevBox - cuda
qpod_cuda-dev:
name: 'full-cuda,cuda-dev'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
source ./tool.sh && free_diskspace
build_image cuda-dev latest docker_devbox/Dockerfile \
--build-arg "BASE_IMG=core-cuda" \
--build-arg "ARG_PROFILE_JUPYTER=base,kernels,extensions" \
--build-arg "ARG_PROFILE_VSCODE=base"
alias_image cuda-dev latest full-cuda latest && push_image

## Sync all images in this build (listed by "names") to mirror registry.
sync_images:
needs: ['docker_kit']
needs: ["qpod_cuda-dev"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
source ./tool.sh
setup_docker_syncer
echo "Syncing image to mirror registry..."
python docker_docker_kit/work/image-syncer/run_jobs.py
printenv > /tmp/docker.env
docker run --rm \
--env-file /tmp/docker.env \
-v $(pwd):/tmp \
-w /tmp \
${DOCKER_IMG_PREFIX:-qpod}/docker-kit python /opt/utils/image-syncer/run_jobs.py
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,46 @@
# dev-lab
# QPod Lab Dev - Docker Image Stack

[![License](https://img.shields.io/badge/License-BSD%203--Clause-green.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/QPod/lab-dev/build-docker.yml?branch=main)](https://github.com/QPod/lab-dev/actions/workflows/build-docker.yml)
[![Recent Code Update](https://img.shields.io/github/last-commit/QPod/lab-dev.svg)](https://github.com/QPod/lab-dev/stargazers)
[![Visit Images on DockerHub](https://img.shields.io/badge/DockerHub-Images-green)](https://hub.docker.com/u/qpod)

Please generously STAR★ our project or donate to us! [![GitHub Starts](https://img.shields.io/github/stars/QPod/lab-dev.svg?label=Stars&style=social)](https://github.com/QPod/lab-dev/stargazers)
[![Donate-PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/haobibo)
[![Donate-AliPay](https://img.shields.io/badge/Donate-Alipay-blue.svg)](https://raw.githubusercontent.com/wiki/haobibo/resources/img/Donate-AliPay.png)
[![Donate-WeChat](https://img.shields.io/badge/Donate-WeChat-green.svg)](https://raw.githubusercontent.com/wiki/haobibo/resources/img/Donate-WeChat.png)

Discussion and contributions are welcome:
[![Join the Discord Chat](https://img.shields.io/badge/Discuss_on-Discord-green)](https://discord.gg/kHUzgQxgbJ)
[![Open an Issue on GitHub](https://img.shields.io/github/issues/QPod/lab-foundation)](https://github.com/QPod/lab-foundation/issues)

## Lab Dev - Building Blocks and IDEs for Application Development

`QPod lab-dev` ( [DockerHub](https://hub.docker.com/u/qpod) | [GitHub](https://github.com/QPod/lab-dev) ) provides Building Blocks and IDEs for Application Development.

## Documentation & Tutorial

[Wiki & Document](https://qpod.github.io/) | [中文使用指引(含中国网络镜像)](https://qpod.github.io/docs/intro-cn)

## Screenshot and Arch Diagram

![Screenshot of QPod](https://raw.githubusercontent.com/wiki/QPod/qpod-hub/img/QPod-screenshot.webp "Screenshot of QPod")

![Arch Diagram for QPod DevBox](https://raw.githubusercontent.com/wiki/QPod/docker-images/img/QPod-arch.svg "Arch Diagram for QPod DevBox")

## Develop and Debug

```bash
IMG="qpod/developer"
# IMG="registry.cn-hangzhou.aliyuncs.com/qpod/developer"

docker run -d --restart=always \
--name=QPod-lab-dev \
--hostname=QPod \
-p 18888-18890:8888-8890 \
-v $(pwd):/root/lab-dev \
-w /root/lab-dev \
$IMG

sleep 5s && docker logs QPod-lab-dev 2>&1|grep token=
```
12 changes: 12 additions & 0 deletions docker_app_clash/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM alpine AS builder

# https://github.com/haishanh/yacd
WORKDIR /tmp
RUN wget https://github.com/haishanh/yacd/archive/gh-pages.zip \
&& unzip ./*.zip && rm -rf *.zip \
&& mv ./* ./ui

# https://github.com/Dreamacro/clash
FROM dreamacro/clash-premium
COPY --from=builder /tmp/* /root/.config/clash/ui
COPY config.yaml /root/.config/clash/
20 changes: 20 additions & 0 deletions docker_app_clash/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# https://github.com/Dreamacro/clash/wiki/configuration#all-configuration-options
mixed-port: 7890
external-controller: :9090
allow-lan: true
bind-address: '*'
log-level: debug
mode: Rule
external-ui: ui

rules:
- DOMAIN-SUFFIX,local,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,100.64.0.0/10,DIRECT,no-resolve
- IP-CIDR6,::1/128,DIRECT,no-resolve
- IP-CIDR6,fc00::/7,DIRECT,no-resolve
- IP-CIDR6,fe80::/10,DIRECT,no-resolve
- IP-CIDR6,fd00::/8,DIRECT,no-resolve
17 changes: 17 additions & 0 deletions docker_app_clash/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: '3.9'

# ref1: https://github.com/Dreamacro/clash/wiki/Run-clash-in-docker
# ref2: https://github.com/Dreamacro/clash/wiki/configuration

services:
svc-clash:
image: 0x06/clash-premium
container_name: svc-clash
restart: unless-stopped
volumes:
- ./config.yaml:/root/.config/clash/config.yaml:ro
ports:
- "7890:7890"
- "9999:9090"
# When your system is Linux, you can use `network_mode: "host"` directly.
# network_mode: "host"
48 changes: 48 additions & 0 deletions docker_devbox/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Distributed under the terms of the Modified BSD License.

ARG BASE_NAMESPACE
ARG BASE_IMG="core"
FROM ${BASE_NAMESPACE:+$BASE_NAMESPACE/}${BASE_IMG}

LABEL maintainer="haobibo@gmail.com"

# base,kernels,extensions
ARG ARG_PROFILE_JUPYTER=base

# base
ARG ARG_PROFILE_VSCODE=base

ARG ARG_KEEP_NODEJS=true

COPY work /opt/utils/

# Setup Jupyter: Basic Configurations and Extensions...
RUN mkdir -pv /opt/conda/etc/jupyter/ \
&& mv /opt/utils/etc_jupyter/* /opt/conda/etc/jupyter/ && rm -rf /opt/utils/etc_jupyter \
&& mv /opt/utils/start-*.sh /usr/local/bin/ && chmod +x /usr/local/bin/start-*.sh \
&& source /opt/utils/script-devbox-jupyter.sh \
&& for profile in $(echo $ARG_PROFILE_JUPYTER | tr "," "\n") ; do ( setup_jupyter_${profile} || true ) ; done

# If not keeping NodeJS, remove NoedJS to reduce image size
RUN ${ARG_KEEP_NODEJS:-true} || ( echo "Removing Node/NPM..." && rm -rf /usr/bin/node /usr/bin/npm /usr/bin/npx /opt/node )

# If installing coder-server # https://github.com/cdr/code-server/releases
RUN source /opt/utils/script-devbox-vscode.sh \
&& for profile in $(echo $ARG_PROFILE_VSCODE | tr "," "\n") ; do ( setup_vscode_${profile} || true ) ; done

# Clean up and display components version information...
RUN source /opt/utils/script-utils.sh && install__clean && list_installed_packages

WORKDIR $HOME_DIR
EXPOSE 8888

ENTRYPOINT ["tini", "-g", "--"]
CMD ["start-notebook.sh"]

# '-c' option make bash commands are read from string.
# If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
# '-o pipefail' prevents errors in a pipeline from being masked.
# If any command in a pipeline fails, that return code will be used as the return code of the whole pipeline.
# '--login': make bash first reads and executes commands from the file /etc/profile, if that file exists.
# After that, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
SHELL ["/bin/bash", "--login", "-o", "pipefail", "-c"]
11 changes: 11 additions & 0 deletions docker_devbox/work/etc_jupyter/jupyter_server_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"ServerApp": {
"ip": "0.0.0.0",
"port": 8888,
"root_dir": "/root",
"default_url": "/lab",
"allow_root": true,
"allow_origin": "*",
"open_browser": false
}
}
5 changes: 5 additions & 0 deletions docker_devbox/work/install_list_JPY_extend.apt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
% This file contains apt packages to be installed with apt-get install line by line.
% Use percent char as line comment separator.

libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev % optional libs to install JS lib canvas
libzmq3-dev % required to build some jupyter kernels like libpango
10 changes: 10 additions & 0 deletions docker_devbox/work/install_list_JPY_extend.pip
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
% This file contains python packages to be installed with pip line by line.
% Use percent char as line comment separator.

ipyparallel % https://github.com/ipython/ipyparallel
ipynb % https://github.com/ipython/ipynb
jupyter-resource-usage % https://github.com/jupyter-server/jupyter-resource-usage
jupyterlab_server[openapi] % https://github.com/jupyterlab/jupyterlab_server
jupyterlab-git % https://github.com/jupyterlab/jupyterlab-git
% jupyter-collaboration % https://github.com/jupyterlab/jupyter-collaboration
% jupyterlab-latex % bug on pypi version: https://github.com/jupyterlab/jupyterlab-latex
81 changes: 81 additions & 0 deletions docker_devbox/work/script-devbox-jupyter.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
source /opt/utils/script-utils.sh


setup_jupyter_base() {
pip install -Uq --pre jupyterhub jupyterlab notebook ipywidgets jupyter-server-proxy \
&& echo "@ Version of Jupyter Server: $(jupyter server --version)" \
&& echo "@ Version of Jupyter Lab: $(jupyter lab --version)" \
&& echo "@ Version of Jupyter Notebook: $(jupyter notebook --version)" \
&& echo "@ Version of JupyterHub: $(jupyterhub --version)"
}


setup_jupyter_kernels() {
echo "@ Jupyter Kernels RefList: https://github.com/jupyter/jupyter/wiki/Jupyter-kernels"

echo "@ Install Jupyter Kernel for Bash" \
&& pip install -Uq bash_kernel && python -m bash_kernel.install --sys-prefix

## checked @ 2024-0307
which npm \
&& echo "@ Install Jupyter Kernel for JavaScript/TypeScript: https://github.com/yunabe/tslab" \
&& npm install -g tslab \
&& tslab install --sys-prefix --python /opt/conda/bin/python --binary $(which tslab)
## ref: https://github.com/n-riesco/ijavascript (#TODO: not working for now)
# && npm_config_zmq_external=true npm install -g --unsafe-perm ijavascript \
# && /opt/node/bin/ijsinstall --install=global --spec-path=full \
# && mv /usr/local/share/jupyter/kernels/javascript /opt/conda/share/jupyter/kernels/

## checked @ 2024-0307 # TODO: help func requries proxy
which R \
&& echo "@ Install Jupyter Kernel for R: https://github.com/melff/RKernel" \
&& R -e "devtools::install_github('melff/RKernel/pkg')" \
&& R -e "RKernel::installspec(user=FALSE)" \
&& mv /usr/local/share/jupyter/kernels/rkernel /opt/conda/share/jupyter/kernels/

## checked @ 2024-0307
which go \
&& echo "@ Install Jupyter Kernel for Golang: https://github.com/janpfeifer/gonb" \
&& export GOPATH=/opt/go/path \
&& go install github.com/janpfeifer/gonb@latest \
&& go install golang.org/x/tools/cmd/goimports@latest \
&& go install golang.org/x/tools/gopls@latest \
&& $GOPATH/bin/gonb --install \
&& mv ~/.local/share/jupyter/kernels/gonb /opt/conda/share/jupyter/kernels/

## TODO: buggy, cargo install sccache
which rustc \
&& echo "@ Install Jupyter Kernel for Rust: https://github.com/evcxr/evcxr/issues/140" \
&& cargo install --locked evcxr_jupyter \
&& evcxr_jupyter --install --sys-prefix \
&& mv ~/.local/share/jupyter/kernels/rust /opt/conda/share/jupyter/kernels/

## TODO: buggy
which java \
&& pip install -Uq pandas py4j
#&& pip install beakerx && beakerx install \
#&& jupyter labextension install beakerx-jupyterlab

## checked @ 2024-0307
which julia \
&& echo "@ Install Jupyter Kernel for Julia: https://github.com/JuliaLang/IJulia.jl" \
&& julia -e "using Pkg; Pkg.add(\"IJulia\"); Pkg.precompile();" \
&& mv ~/.local/share/jupyter/kernels/julia* /opt/conda/share/jupyter/kernels/

## https://github.com/jupyter-xeus/xeus-octave # TODO: to check
which octave \
&& export PATH=/opt/octave/bin:$PATH \
&& pip install -Uq xeus-python

echo "@ Installed Jupyter Kernels:" && jupyter kernelspec list
}


setup_jupyter_extensions() {
install_apt /opt/utils/install_list_JPY_extend.apt \
&& install_pip /opt/utils/install_list_JPY_extend.pip

echo "@ Jupyter Server Extension list: " && jupyter server extension list \
&& echo "@ Jupyter Lab Extension list: " && jupyter labextension list \
&& echo "@ Jupyter Notebook Extension list: " && jupyter notebook extension list
}
13 changes: 13 additions & 0 deletions docker_devbox/work/script-devbox-vscode.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
source /opt/utils/script-utils.sh

# ref: https://github.com/coder/code-server

setup_vscode_base() {
VERSION_CODER=$(curl -sL https://github.com/cdr/code-server/releases.atom | grep "releases/tag" | head -1 | grep -Po '(\d[\d|.]+)') \
&& install_tar_gz "https://github.com/cdr/code-server/releases/download/v${VERSION_CODER}/code-server-${VERSION_CODER}-linux-amd64.tar.gz" \
&& mv /opt/code-server* /opt/code-server \
&& ln -s /opt/code-server/bin/code-server /usr/bin/ \
&& printf "#!/bin/bash\n/opt/code-server/bin/code-server --port=8888 --auth=none --disable-telemetry ${HOME}\n" > /usr/local/bin/start-code-server.sh \
&& chmod u+x /usr/local/bin/start-code-server.sh \
&& echo "@ coder-server Version: $(code-server -v)"
}
17 changes: 17 additions & 0 deletions docker_devbox/work/start--pre.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
set -e

# Utilities function to compare version.
ver_gte() { [ "$2" = "`echo -e "$1\n$2" | sort -V | head -n1`" ]; }

# Generate a SSH id for git if it does not exist.
[ -e ~/.ssh/id_rsa.pub ] || ssh-keygen -t rsa -b 4096 -N "" -C `hostname -f` -f ~/.ssh/id_rsa

# Generate a self-signed certificate for notebook if it does not exist (only when GEN_CERT or USE_SSL is set to yes).
NOTEBOOK_PEM_FILE="/opt/conda/etc/jupyter/notebook.pem"
( [ -n "${GEN_CERT:+x}" ] || [ -n "${USE_SSL:+x}" ] ) && [ ! -f ${NOTEBOOK_PEM_FILE} ] && ( openssl req -new -newkey rsa:2048 \
-days 356 -nodes -x509 -subj "/C=XX/ST=XX/L=XX/O=generated/CN=generated" -keyout $NOTEBOOK_PEM_FILE -out $NOTEBOOK_PEM_FILE \
&& chmod 600 $NOTEBOOK_PEM_FILE )

# Print something so running this script returns a non-zero return code
echo "Pre-start work done!"
14 changes: 14 additions & 0 deletions docker_devbox/work/start-jupyterlab.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
. $DIR/start--pre.sh

NOTEBOOK_ARGS=""
[ -n "${USE_SSL:+x}" ] && NOTEBOOK_ARGS="${NOTEBOOK_ARGS} --NotebookApp.certfile=${NOTEBOOK_PEM_FILE}"


if [[ ! -z "${JUPYTERHUB_API_TOKEN}" ]]; then
# launched by JupyterHub, use single-user entrypoint
exec $DIR/start-singleuser.sh $*
else
jupyter lab ${NOTEBOOK_ARGS} $*
fi
14 changes: 14 additions & 0 deletions docker_devbox/work/start-notebook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
. $DIR/start--pre.sh

NOTEBOOK_ARGS=""
[ -n "${USE_SSL:+x}" ] && NOTEBOOK_ARGS="${NOTEBOOK_ARGS} --NotebookApp.certfile=${NOTEBOOK_PEM_FILE}"


if [[ ! -z "${JUPYTERHUB_API_TOKEN}" ]]; then
# launched by JupyterHub, use single-user entrypoint
exec $DIR/start-singleuser.sh $*
else
jupyter notebook ${NOTEBOOK_ARGS} $*
fi
Loading