GithubHelp home page GithubHelp logo

termux-docker's Introduction

Termux environment for Docker/Podman.

A Termux environment packaged into Docker image. Environment doesn't have Android runtime components, so certain things will not be available (DalvikVM, OpenSLES, etc...).

How to use

Requirements

You should have a properly configured and running Docker or Podman container systems. Further instructions will provide examples only for Docker.

Basic usage

This will start interactive login shell. Everything will look like in a normal Termux installation.

docker run -it termux/termux-docker:latest

When using the tag latest, container will be 32 bit (i686 architecture).

Other architecture can be installed using a different tags. Available tags:

  • aarch64
  • arm
  • i686 (latest)
  • x86_64

If architecture is not compatible with host, the additional setup will be needed. Read this document further to learn how you can run containers of incompatible CPU architecture.

Important note: do not pass --user option to Docker command line. The initial user of container must be root. Otherwise DNS will be broken because of dnsmasq server failure.

Running ARM containers on x86 host

In order to run AArch64 container on x86(64) host, you need to setup QEMU emulator through binfmt_misc. This can be easily done by one command:

docker run --rm --privileged aptman/qus -s -- -p aarch64 arm

Note that AArch64 and ARM containers work properly only in privileged mode. If you want your containers to have standard privileges, a custom seccomp profile is required.

Variant with privileged container:

docker run -it --privileged termux/termux-docker:aarch64

Variant with seccomp unconfined profile:

docker run -it --security-opt seccomp:unconfined termux/termux-docker:aarch64

Non-interactive execution of commands

You can run commands in non-interactive mode. Just append them to Docker command line.

Example:

docker run -it --rm termux/termux-docker:latest bash -c "apt update && apt install -yq clang"

Root shell

By default root shell is disabled in container as Termux doesn't really support usage of package manager under root account. In cases where you really need shell with root privileges, entrypoint should be overridden.

The provided images have 2 entry points:

  • /entrypoint.sh - the standard one which drops privileges to system user.
  • /entrypoint_root.sh - alternate entrypoint that does not drop privileges.

Usage example:

docker run -it --entrypoint /entrypoint_root.sh termux/termux-docker:latest

Building image

Docker:

./build-all.sh

Podman:

./build-all.sh --podman

Known issues

There a number of known issues which may not be resolved:

  • ARM containers may require a custom seccomp profile to remove restrictions from personality() system call.

  • When running certain multi threaded program in 32bit containers, the PIDs can balloon and easily exceed libc's limit. The only way to fix this is to set /proc/sys/kernel/pid_max to 65535. See termux-docker#40.

termux-docker's People

Contributors

dependabot[bot] avatar deshdeepak1 avatar grimler91 avatar kcubeterm avatar landfillbaby avatar lars18th avatar licy183 avatar nisheri-ascar avatar rojenzaman avatar truboxl avatar umarcor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

termux-docker's Issues

termux-docker images should be properly labeled with their native arch

https://hub.docker.com/r/termux/termux-docker/tags

Currently all the images are labelled as linux/amd64. I think they should be properly fixed so that supposedly they can run on their own native architectures without any Docker warnings.

  1. Though I am not quite settled for:
    arm to use linux/arm or linux/arm/v7 or linux/arm32v7?
    aarch64 to use linux/aarch64 or linux/arm/v8 or linux/arm64 or linux/arm64v8?
    i686 (which is also "latest") to change to linux/i386?

  2. We also need to look into adding busybox that are native to their arches
    The one at https://github.com/termux/termux-docker/blob/4c08c24bceb13cecd1d18153dfddbbf5fe70bb71/system/arm/bin/busybox is currently 32bit arm static binary (checksum cd04052b8b6885f75f50b2a280bfcbf849d8710c8e61d369c533acf307eda064) which based on https://github.com/hazy/google-distroless/blob/master/WORKSPACE#L423 is coming from https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/

GitHub Actions: `pkg install` not working, `None of the mirrors are accessible`

Thanks a lot for making this docker image!

When working on rami3l/pacaptr#587, I want to be able to use the Termux environment in my CI for testing purposes. My usage in the manifest is something like the following:

  apt-termux-test:
    runs-on: ubuntu-latest
    needs: skip-check
    if: ${{ needs.skip-check.outputs.should_skip != 'true' }}
    container:
      image: termux/termux-docker:latest
      # https://github.com/termux/termux-docker#root-shell
      options: --user system
   ...

However, pkg install won't work and gives the following error:

Run pkg install -y curl build-essential
No mirror or mirror group selected. You might want to select one by running 'termux-change-repo'
Testing the available mirrors:
[*] (10) https://packages-cf.termux.dev/apt/termux-main: bad
[*] (1) https://mirror.textcord.xyz/termux/termux-main: bad
[*] (1) https://packages.nscdn.top/termux-main: bad
[*] (1) https://mirror.albony.xyz/termux/termux-main: bad
[*] (1) https://mirror.bardia.tech/termux/termux-main: bad
[*] (1) https://mirror.nevacloud.com/applications/termux/termux-main: bad
[*] (1) https://linux.domainesia.com/applications/termux/termux-main: bad
[*] (1) https://mirrors.cbrx.io/apt/termux/termux-main: bad
[*] (1) https://mirror.nyist.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.hit.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.cqupt.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.ustc.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.scau.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.bfsu.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.nju.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.zju.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.njupt.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.pku.edu.cn/termux/termux-main/: bad
[*] (1) https://mirrors.dgut.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.aliyun.com/termux/termux-main: bad
[*] (1) https://mirrors.sdu.edu.cn/termux/termux-main: bad
[*] (1) https://mirror.iscas.ac.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.sau.edu.cn/termux/apt/termux-main: bad
[*] (1) https://mirrors.sustech.edu.cn/termux/apt/termux-main: bad
[*] (1) https://termux.cdn.lumito.net/termux-main: bad
[*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad
[*] (1) https://termux.astra.in.ua/apt/termux-main: bad
[*] (1) https://mirror.mwt.me/termux/main: bad
[*] (4) https://grimler.se/termux/termux-main: bad
[*] (1) https://termux.mentality.rip/termux-main: bad
[*] (1) https://mirror.termux.dev/termux-main: bad
[*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: bad
[*] (1) https://termux.3san.dev/termux/termux-main: bad
[*] (1) https://termux.librehat.com/apt/termux-main: bad
[*] (1) https://mirrors.sahilister.in/termux/termux-main: bad
[*] (1) https://ftp.fau.de/termux/termux-main: bad
[*] (1) https://packages.termux.dev/apt/termux-main: bad
[*] (1) https://mirror.fcix.net/termux/termux-main: bad
[*] (1) https://plug-mirror.rcac.purdue.edu/termux/termux-main: bad
[*] (1) https://mirrors.utermux.dev/termux/termux-main: bad
[*] (1) https://mirror.mwt.me/termux/main: bad
[*] (1) https://mirror.csclub.uwaterloo.ca/termux/termux-main: bad
[*] (1) https://mirror.vern.cc/termux/termux-main: bad
[*] (1) https://dl.kcubeterm.com/termux-main: bad
[*] (1) https://mirrors.wale.id.au/termux/termux-main: bad
[*] (1) http://mirror.mephi.ru/termux/termux-main: bad
[*] (1) https://mirror.surf/termux/termux-main/: bad
Error: None of the mirrors are accessible
Error: Process completed with exit code 1.

Changing image to termux/termux-docker:x86_64 doesn't make any difference.

Full Log
2023-05-27T02:16:16.7408456Z Requested labels: ubuntu-latest
2023-05-27T02:16:16.7408703Z Job defined at: rami3l/pacaptr/.github/workflows/test.yml@refs/pull/587/merge
2023-05-27T02:16:16.7408852Z Waiting for a runner to pick up this job...
2023-05-27T02:16:17.0597270Z Job is waiting for a hosted runner to come online.
2023-05-27T02:16:19.1599498Z Job is about to start running on the hosted runner: GitHub Actions 6 (hosted)
2023-05-27T02:16:21.8918242Z Current runner version: '2.304.0'
2023-05-27T02:16:21.8946673Z ##[group]Operating System
2023-05-27T02:16:21.8947276Z Ubuntu
2023-05-27T02:16:21.8947531Z 22.04.2
2023-05-27T02:16:21.8947823Z LTS
2023-05-27T02:16:21.8948215Z ##[endgroup]
2023-05-27T02:16:21.8948502Z ##[group]Runner Image
2023-05-27T02:16:21.8948892Z Image: ubuntu-22.04
2023-05-27T02:16:21.8949231Z Version: 20230507.1
2023-05-27T02:16:21.8949725Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20230507.1/images/linux/Ubuntu2204-Readme.md
2023-05-27T02:16:21.8950438Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20230507.1
2023-05-27T02:16:21.8950912Z ##[endgroup]
2023-05-27T02:16:21.8951287Z ##[group]Runner Image Provisioner
2023-05-27T02:16:21.8951594Z 2.0.171.1
2023-05-27T02:16:21.8951929Z ##[endgroup]
2023-05-27T02:16:21.8952929Z ##[group]GITHUB_TOKEN Permissions
2023-05-27T02:16:21.8953631Z Actions: write
2023-05-27T02:16:21.8953911Z Checks: write
2023-05-27T02:16:21.8954490Z Contents: write
2023-05-27T02:16:21.8954889Z Deployments: write
2023-05-27T02:16:21.8955233Z Discussions: write
2023-05-27T02:16:21.8955608Z Issues: write
2023-05-27T02:16:21.8955878Z Metadata: read
2023-05-27T02:16:21.8956206Z Packages: write
2023-05-27T02:16:21.8956530Z Pages: write
2023-05-27T02:16:21.8956815Z PullRequests: write
2023-05-27T02:16:21.8957224Z RepositoryProjects: write
2023-05-27T02:16:21.8957619Z SecurityEvents: write
2023-05-27T02:16:21.8957913Z Statuses: write
2023-05-27T02:16:21.8958237Z ##[endgroup]
2023-05-27T02:16:21.8962000Z Secret source: Actions
2023-05-27T02:16:21.8962474Z Prepare workflow directory
2023-05-27T02:16:21.9990252Z Prepare all required actions
2023-05-27T02:16:22.0173885Z Getting action download info
2023-05-27T02:16:22.2311989Z Download action repository 'actions/checkout@v3' (SHA:8e5e7e5ab8b370d6c329ec480221332ada57f0ab)
2023-05-27T02:16:22.5529843Z Download action repository 'dtolnay/rust-toolchain@stable' (SHA:07a68733c10c6a230a22a9c7d3dbaeaf4d00544f)
2023-05-27T02:16:22.7071322Z Download action repository 'Swatinem/rust-cache@v2' (SHA:988c164c3d0e93c4dbab36aaf5bbeb77425b2894)
2023-05-27T02:16:23.0769412Z Complete job name: apt-termux-test
2023-05-27T02:16:23.1445674Z ##[group]Checking docker version
2023-05-27T02:16:23.1462001Z ##[command]/usr/bin/docker version --format '{{.Server.APIVersion}}'
2023-05-27T02:16:23.2717465Z '1.41'
2023-05-27T02:16:23.2735511Z Docker daemon API version: '1.41'
2023-05-27T02:16:23.2736025Z ##[command]/usr/bin/docker version --format '{{.Client.APIVersion}}'
2023-05-27T02:16:23.2984093Z '1.41'
2023-05-27T02:16:23.2986663Z Docker client API version: '1.41'
2023-05-27T02:16:23.2992878Z ##[endgroup]
2023-05-27T02:16:23.2996506Z ##[group]Clean up resources from previous jobs
2023-05-27T02:16:23.3002591Z ##[command]/usr/bin/docker ps --all --quiet --no-trunc --filter "label=ed866e"
2023-05-27T02:16:23.3232801Z ##[command]/usr/bin/docker network prune --force --filter "label=ed866e"
2023-05-27T02:16:23.3420304Z ##[endgroup]
2023-05-27T02:16:23.3420695Z ##[group]Create local container network
2023-05-27T02:16:23.3431779Z ##[command]/usr/bin/docker network create --label ed866e github_network_436b870d1ccc43cc987bb91321a99745
2023-05-27T02:16:23.4098293Z 3160ef0c2bb77c517cd75b2f128a676aea5102e720be33c27a3eafe622dc29c8
2023-05-27T02:16:23.4120373Z ##[endgroup]
2023-05-27T02:16:23.4210958Z ##[group]Starting job container
2023-05-27T02:16:23.4231775Z ##[command]/usr/bin/docker pull termux/termux-docker:x86_64
2023-05-27T02:16:23.7629249Z x86_64: Pulling from termux/termux-docker
2023-05-27T02:16:23.7636091Z e54c40457867: Pulling fs layer
2023-05-27T02:16:23.7646690Z 4f4fb700ef54: Pulling fs layer
2023-05-27T02:16:23.8396950Z 4f4fb700ef54: Verifying Checksum
2023-05-27T02:16:23.8397291Z 4f4fb700ef54: Download complete
2023-05-27T02:16:24.7129602Z e54c40457867: Verifying Checksum
2023-05-27T02:16:24.7129987Z e54c40457867: Download complete
2023-05-27T02:16:26.0445852Z e54c40457867: Pull complete
2023-05-27T02:16:26.4142036Z 4f4fb700ef54: Pull complete
2023-05-27T02:16:26.4180477Z Digest: sha256:d248c40fb977eb9d48416dcbbc047caec21d2c81dd15b9c2a4cd223b67af2b7d
2023-05-27T02:16:26.4242119Z Status: Downloaded newer image for termux/termux-docker:x86_64
2023-05-27T02:16:26.4255487Z docker.io/termux/termux-docker:x86_64
2023-05-27T02:16:26.4393098Z ##[command]/usr/bin/docker create --name 2690af2e11514a4c812499c97eabbf00_termuxtermuxdockerx86_64_2b404f --label ed866e --workdir /__w/pacaptr/pacaptr --network github_network_436b870d1ccc43cc987bb91321a99745 --user system -e "HOME=/github/home" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work":"/__w" -v "/home/runner/runners/2.304.0/externals":"/__e":ro -v "/home/runner/work/_temp":"/__w/_temp" -v "/home/runner/work/_actions":"/__w/_actions" -v "/opt/hostedtoolcache":"/__t" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" --entrypoint "tail" termux/termux-docker:x86_64 "-f" "/dev/null"
2023-05-27T02:16:26.4777067Z b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6
2023-05-27T02:16:26.4801028Z ##[command]/usr/bin/docker start b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6
2023-05-27T02:16:26.8056523Z b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6
2023-05-27T02:16:26.8070485Z ##[command]/usr/bin/docker ps --all --filter id=b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6 --filter status=running --no-trunc --format "{{.ID}} {{.Status}}"
2023-05-27T02:16:26.8251635Z b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6 Up Less than a second
2023-05-27T02:16:26.8271590Z ##[command]/usr/bin/docker inspect --format "{{range .Config.Env}}{{println .}}{{end}}" b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6
2023-05-27T02:16:26.8434426Z CI=true
2023-05-27T02:16:26.8434969Z HOME=/github/home
2023-05-27T02:16:26.8446301Z GITHUB_ACTIONS=true
2023-05-27T02:16:26.8446794Z PATH=/data/data/com.termux/files/usr/bin
2023-05-27T02:16:26.8450254Z ANDROID_DATA=/data
2023-05-27T02:16:26.8450804Z ANDROID_ROOT=/system
2023-05-27T02:16:26.8451692Z LANG=en_US.UTF-8
2023-05-27T02:16:26.8452534Z PREFIX=/data/data/com.termux/files/usr
2023-05-27T02:16:26.8453313Z TMPDIR=/data/data/com.termux/files/usr/tmp
2023-05-27T02:16:26.8453723Z TZ=UTC
2023-05-27T02:16:26.8478002Z ##[endgroup]
2023-05-27T02:16:26.8509169Z ##[group]Waiting for all services to be ready
2023-05-27T02:16:26.8510939Z ##[endgroup]
2023-05-27T02:16:26.8820616Z ##[group]Run pkg install -y curl build-essential
2023-05-27T02:16:26.8820988Z ๏ฟฝ[36;1mpkg install -y curl build-essential๏ฟฝ[0m
2023-05-27T02:16:26.8824496Z shell: sh -e {0}
2023-05-27T02:16:26.8824705Z env:
2023-05-27T02:16:26.8824900Z   CARGO_TERM_COLOR: always
2023-05-27T02:16:26.8825169Z   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
2023-05-27T02:16:26.8825416Z ##[endgroup]
2023-05-27T02:16:27.0192741Z No mirror or mirror group selected. You might want to select one by running 'termux-change-repo'
2023-05-27T02:16:27.0208875Z Testing the available mirrors:
2023-05-27T02:16:27.1067739Z [*] (10) https://packages-cf.termux.dev/apt/termux-main: bad
2023-05-27T02:16:27.1068222Z [*] (1) https://mirror.textcord.xyz/termux/termux-main: bad
2023-05-27T02:16:27.1068630Z [*] (1) https://packages.nscdn.top/termux-main: bad
2023-05-27T02:16:27.1069032Z [*] (1) https://mirror.albony.xyz/termux/termux-main: bad
2023-05-27T02:16:27.1069495Z [*] (1) https://mirror.bardia.tech/termux/termux-main: bad
2023-05-27T02:16:27.1069935Z [*] (1) https://mirror.nevacloud.com/applications/termux/termux-main: bad
2023-05-27T02:16:27.1070408Z [*] (1) https://linux.domainesia.com/applications/termux/termux-main: bad
2023-05-27T02:16:27.1070839Z [*] (1) https://mirrors.cbrx.io/apt/termux/termux-main: bad
2023-05-27T02:16:27.1071256Z [*] (1) https://mirror.nyist.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1071666Z [*] (1) https://mirrors.hit.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1846647Z [*] (1) https://mirrors.cqupt.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1847555Z [*] (1) https://mirrors.ustc.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1847968Z [*] (1) https://mirrors.scau.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1848395Z [*] (1) https://mirrors.bfsu.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1848817Z [*] (1) https://mirrors.nju.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1849291Z [*] (1) https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1849730Z [*] (1) https://mirrors.zju.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1850155Z [*] (1) https://mirrors.njupt.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.1850580Z [*] (1) https://mirrors.pku.edu.cn/termux/termux-main/: bad
2023-05-27T02:16:27.1850990Z [*] (1) https://mirrors.dgut.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.2648468Z [*] (1) https://mirrors.aliyun.com/termux/termux-main: bad
2023-05-27T02:16:27.2648938Z [*] (1) https://mirrors.sdu.edu.cn/termux/termux-main: bad
2023-05-27T02:16:27.2763346Z [*] (1) https://mirror.iscas.ac.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.2763803Z [*] (1) https://mirrors.sau.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.2764244Z [*] (1) https://mirrors.sustech.edu.cn/termux/apt/termux-main: bad
2023-05-27T02:16:27.2764666Z [*] (1) https://termux.cdn.lumito.net/termux-main: bad
2023-05-27T02:16:27.2765098Z [*] (1) https://md.mirrors.hacktegic.com/termux/termux-main: bad
2023-05-27T02:16:27.2765715Z [*] (1) https://termux.astra.in.ua/apt/termux-main: bad
2023-05-27T02:16:27.2766118Z [*] (1) https://mirror.mwt.me/termux/main: bad
2023-05-27T02:16:27.2766510Z [*] (4) https://grimler.se/termux/termux-main: bad
2023-05-27T02:16:27.3767638Z [*] (1) https://termux.mentality.rip/termux-main: bad
2023-05-27T02:16:27.3768429Z [*] (1) https://mirror.termux.dev/termux-main: bad
2023-05-27T02:16:27.3768920Z [*] (1) https://mirror.accum.se/mirror/termux.dev/termux-main: bad
2023-05-27T02:16:27.3769586Z [*] (1) https://termux.3san.dev/termux/termux-main: bad
2023-05-27T02:16:27.3770063Z [*] (1) https://termux.librehat.com/apt/termux-main: bad
2023-05-27T02:16:27.3770558Z [*] (1) https://mirrors.sahilister.in/termux/termux-main: bad
2023-05-27T02:16:27.3771023Z [*] (1) https://ftp.fau.de/termux/termux-main: bad
2023-05-27T02:16:27.3771446Z [*] (1) https://packages.termux.dev/apt/termux-main: bad
2023-05-27T02:16:27.3771975Z [*] (1) https://mirror.fcix.net/termux/termux-main: bad
2023-05-27T02:16:27.3774689Z [*] (1) https://plug-mirror.rcac.purdue.edu/termux/termux-main: bad
2023-05-27T02:16:27.4498693Z [*] (1) https://mirrors.utermux.dev/termux/termux-main: bad
2023-05-27T02:16:27.4503222Z [*] (1) https://mirror.mwt.me/termux/main: bad
2023-05-27T02:16:27.4504051Z [*] (1) https://mirror.csclub.uwaterloo.ca/termux/termux-main: bad
2023-05-27T02:16:27.4505394Z [*] (1) https://mirror.vern.cc/termux/termux-main: bad
2023-05-27T02:16:27.4506046Z [*] (1) https://dl.kcubeterm.com/termux-main: bad
2023-05-27T02:16:27.4507132Z [*] (1) https://mirrors.wale.id.au/termux/termux-main: bad
2023-05-27T02:16:27.4507592Z [*] (1) http://mirror.mephi.ru/termux/termux-main: bad
2023-05-27T02:16:27.4508165Z [*] (1) https://mirror.surf/termux/termux-main/: bad
2023-05-27T02:16:27.4508540Z Error: None of the mirrors are accessible
2023-05-27T02:16:27.4565175Z ##[error]Process completed with exit code 1.
2023-05-27T02:16:27.4775731Z Stop and remove container: 2690af2e11514a4c812499c97eabbf00_termuxtermuxdockerx86_64_2b404f
2023-05-27T02:16:27.4781349Z ##[command]/usr/bin/docker rm --force b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6
2023-05-27T02:16:27.6758728Z b62fc87d42c787a4649f56c07979a670889308e96ea9568cf0fa4b6b2d7cecd6
2023-05-27T02:16:27.6786091Z Remove container network: github_network_436b870d1ccc43cc987bb91321a99745
2023-05-27T02:16:27.6792132Z ##[command]/usr/bin/docker network rm github_network_436b870d1ccc43cc987bb91321a99745
2023-05-27T02:16:27.8847922Z github_network_436b870d1ccc43cc987bb91321a99745
2023-05-27T02:16:27.8989297Z Cleaning up orphan processes

An interesting finding that might be helpful:

It seems to me that it's probably a problem with the DNS, because when I tried replicating the issue on my ARM Mac:

> docker run --rm --privileged -it termux/termux-docker:aarch64
[!] Failed to start dnsmasq, host name resolution may fail.
Welcome to Termux!

Docs:       https://termux.dev/docs
Donate:     https://termux.dev/donate
Community:  https://termux.dev/community

Working with packages:

 - Search:  pkg search <query>
 - Install: pkg install <package>
 - Upgrade: pkg upgrade

Subscribing to additional repositories:

 - Root:    pkg install root-repo
 - X11:     pkg install x11-repo

For fixing any repository issues,
try 'termux-change-repo' command.

Report issues at https://termux.dev/issues

IPv6 Only support

I am using IPv6 Only VPS. I have configured Docker with IPv6 support and termux-docker with DNS64. However, termux-docker only seems to support IPv4.

~ $ apt update
Ign:1 https://packages.termux.org/apt/termux-main stable InRelease
Ign:2 https://packages.termux.org/apt/termux-games games InRelease
Ign:3 https://packages.termux.org/apt/termux-science science InRelease
Ign:1 https://packages.termux.org/apt/termux-main stable InRelease
Ign:2 https://packages.termux.org/apt/termux-games games InRelease
Ign:3 https://packages.termux.org/apt/termux-science science InRelease
Ign:1 https://packages.termux.org/apt/termux-main stable InRelease
Ign:2 https://packages.termux.org/apt/termux-games games InRelease
Ign:3 https://packages.termux.org/apt/termux-science science InRelease
Err:1 https://packages.termux.org/apt/termux-main stable InRelease
  Could not wait for server fd - select (11: Try again) [IP: 216.18.208.172 443]
Err:2 https://packages.termux.org/apt/termux-games games InRelease
  Could not connect to packages.termux.org:443 (216.18.208.172). - connect (101: Network is unreachable) [IP: 216.18.208.172 443]
Err:3 https://packages.termux.org/apt/termux-science science InRelease
  Unable to connect to packages.termux.org:https: [IP: 216.18.208.172 443]
Reading package lists... Done
Building dependency tree... Done
All packages are up to date.
W: Failed to fetch https://packages.termux.org/apt/termux-main/dists/stable/InRelease  Could not wait for server fd - select (11: Try again) [IP: 216.18.208.172 443]
W: Failed to fetch https://packages.termux.org/apt/termux-games/dists/games/InRelease  Could not connect to packages.termux.org:443 (216.18.208.172). - connect (101: Network is unreachable) [IP: 216.18.208.172 443]
W: Failed to fetch https://packages.termux.org/apt/termux-science/dists/science/InRelease  Unable to connect to packages.termux.org:https: [IP: 216.18.208.172 443]
W: Some index files failed to download. They have been ignored, or old ones used instead.

OCI runtime error: crun: pivot_root: Invalid argument

txmu@ubuntu:~/termux-docker$ sudo ./run.sh --podman 
Creating new container...
Error: OCI runtime error: crun: pivot_root: Invalid argument
Error: can only create exec sessions on running containers: container state improper

OS: Bedrock Linux 0.7.28beta (https://bedrocklinux.org) (Maybe it can be understood as ubuntu 20.04 LTS)
ARCH: arm64

I set the no_pivot_root=true
(See #26 )

podman version 4.0.3

32bit arch must set /proc/sys/kernel/pid_max = 65535

https://android.googlesource.com/platform/bionic/#host-tests
https://android.googlesource.com/platform/bionic/+/master/libc/bionic/libc_init_common.cpp

When running certain multi threaded program in 32bit containers, the PIDs can balloon and easily exceed libc's limit.
The following error will be shown:

Limited by the size of pthread_mutex_t, 32 bit bionic libc only accepts pid <= 65535, but current pid is 65969
libc: Limited by the size of pthread_mutex_t, 32 bit bionic libc only accepts pid <= 65535, but current pid is 65969
libc: Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 65969 (emcc), pid 65969 (emcc)

This was spotted when running emscripten tests in i686 container on x86_64 host
which the pid_max value of both host and container is

$ cat /proc/sys/kernel/pid_max 
4194304

The only way to fix this is to set /proc/sys/kernel/pid_max to 65535 but setting this will affect both container and host globally at runtime. I think we can list this as a caveat.

EDIT: updated to 65535 in 6189bbd. Sorry for the confusion future readers.

(Question) using x11 output in x11-packages

image

hello, I am currently using Manjaro, I installed termux using docker, it works very well, but I can not start x11 packages, not even with vnc, when I run vncserver it gives me an invalid ip address, is there any way to work with these packages from docker?

How to (cross-)compile full static binaries, and execute them for multiple platforms inside the same container

Hi,

This is based on #46. First let me to explain my use case:

  • I want to use the "original" Termux environment in my desktop computer, instead of using my smartphone. The idea is to develop inside this environment. And the architectures are different. So I prefer to use aarch64 in my Termux environment running in my computer. To achieve this I'm using the well know solution of multiarch/qemu-user-static. However, this solution is slow when using some binaries through the emulation layer that could be native. For example, I want to use the psusan (from PuTTY) tool to stablish a link between the container and my PuTTY terminal. This permits to open multiple shell sessions to the same container. But if you use the stock binary (aarch64) it will run emulated. The solution is to execute a version compiled for your native platform (x86_64). But the problem here is that this version requires to be fully static to not try to use any library of the container platform. And that's what I've achieved.

The solution to compile fully static binaries for the Termux environment, is to compile using the "zig cc" tool. Read more about it https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html . As a simple receipt you need to compile for targets like aarch64-linux-musl, x86_64-linux-musl, etc. Then you can execute the outcoming binaries inside your Termux container independely of the platform.

For example, I've compiled the PuTTY package and I get the static psusan.x64. Then I can start the container termux-docker:aarch64 with this binary mounted with docker run --rm -i --mount 'type=bind, .... And after I can use the PuTTY client to connect (multiple times) to the container. While the server "psusan" running inside the container is "x86_64" and not "aarch64". Nice, right?

From this point I suggest to include inside all the containers the static binaries of the psusan tool for different platforms. Then it will be easy to start the container with this tool using the host platform although the container is for a different one. What you think about this suggestion?

[Bug]: clang crashes on aarch64 architecture under x86_64 host when using qemu-static

Problem description

clang crashes/hangs on aarch64 architecture under x86_64 host. It seems to be an upstream issue of qemu-aarch64-static. But actually there is no such issue under other aarch64 rootfs (test with clang under alpine and ubuntu).

What steps will reproduce the bug?

pkg install clang
echo -e "#include <iostream>\nint main() { std::cout << std::endl; }" > main.cpp
clang++ main.cpp -v # hangs
clang++  -std=c++11 main.cpp -v # crashes

Log

clang version 14.0.1
Target: aarch64-unknown-linux-android24
Thread model: posix
InstalledDir: /data/data/com.termux/files/usr/bin
 "/data/data/com.termux/files/usr/bin/clang-14" -cc1 -triple aarch64-unknown-linux-android24 -emit-obj -mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -fallow-half-arguments-and-returns -mllvm -treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v -fcoverage-compilation-dir=/data/data/com.termux/files/home -resource-dir /data/data/com.termux/files/usr/lib/clang/14.0.1 -isysroot /data/data/com.termux/files -internal-isystem /data/data/com.termux/files/usr/include/c++/v1 -internal-isystem /data/data/com.termux/files/usr/lib/clang/14.0.1/include -internal-isystem /data/data/com.termux/files/usr/local/include -internal-externc-isystem /data/data/com.termux/files/usr/include/aarch64-linux-android -internal-externc-isystem /data/data/com.termux/files/include -internal-externc-isystem /data/data/com.termux/files/usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir=/data/data/com.termux/files/home -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /data/data/com.termux/files/usr/tmp/main-1c1e58.o -x c++ main.cpp
clang -cc1 version 14.0.1 based upon LLVM 14.0.1 default target aarch64-unknown-linux-android24
ignoring nonexistent directory "/data/data/com.termux/files/usr/local/include"
ignoring nonexistent directory "/data/data/com.termux/files/include"
#include "..." search starts here:
#include <...> search starts here:
 /data/data/com.termux/files/usr/include/c++/v1
 /data/data/com.termux/files/usr/lib/clang/14.0.1/include
 /data/data/com.termux/files/usr/include/aarch64-linux-android
 /data/data/com.termux/files/usr/include
End of search list.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /data/data/com.termux/files/usr/bin/clang-14 -cc1 -triple aarch64-unknown-linux-android24 -emit-obj -mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -fallow-half-arguments-and-returns -mllvm -treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v -fcoverage-compilation-dir=/data/data/com.termux/files/home -resource-dir /data/data/com.termux/files/usr/lib/clang/14.0.1 -isysroot /data/data/com.termux/files -internal-isystem /data/data/com.termux/files/usr/include/c++/v1 -internal-isystem /data/data/com.termux/files/usr/lib/clang/14.0.1/include -internal-isystem /data/data/com.termux/files/usr/local/include -internal-externc-isystem /data/data/com.termux/files/usr/include/aarch64-linux-android -internal-externc-isystem /data/data/com.termux/files/include -internal-externc-isystem /data/data/com.termux/files/usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir=/data/data/com.termux/files/home -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /data/data/com.termux/files/usr/tmp/main-1c1e58.o -x c++ main.cpp
1.      /data/data/com.termux/files/usr/include/c++/v1/algorithm:3123:1: current parser token '{'
2.      /data/data/com.termux/files/usr/include/c++/v1/algorithm:660:1 <Spelling=/data/data/com.termux/files/usr/include/c++/v1/__config:793:37>: parsing namespace 'std'
3.      /data/data/com.termux/files/usr/include/c++/v1/algorithm:660:1 <Spelling=/data/data/com.termux/files/usr/include/c++/v1/__config:793:60>: parsing namespace 'std::__ndk1'
libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xfffffff0 in tid 980 (clang-14), pid 980 (clang-14)
libc: failed to spawn debuggerd dispatch thread: Invalid argument

How to use `termux-docker` in GitHub Actions?

Hello, I want to test a bash installer script within the termux-docker image using GitHub Actions. While GitHub Actions does support running commands within a custom docker image/container, it does not honor the ENTRYPOINT of the image and insists on running everything as root. Even running the commands explicitly under /entrypoint.sh ... to drop privileges does not seem to work properly, due to permission issues. It also seems that the GitHub Actions actions/checkout module expects node to be installed at /__e/node20/bin/node. I also encountered strange networking issues when executing /entrypoint.sh ... multiple times. Is termux-docker even compatible with GitHub Actions? Maybe this is something that could be documented better?

docker: Cannot connect to the Docker daemon

when i try the to run termux with this command: docker run -it termux/termux-docker:latest it just give me this error: docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

How can i run a docker daemon beacuse i don't know, thanks

Execution of scripts in containers

I am trying to execute a test script inside the aarch64 container, which updates the system and clones a git repo.

set -e

cd $(dirname "$0")

echo '::group::Update'
pkg update
yes | apt upgrade
echo '::endgroup::'

pkg install -y git

ls -la

mkdir -p ghdl
cd ghdl

git clone https://github.com/ghdl/ghdl

By default, these containers' entrypoint is login. Hence, executing commands non-interactively requires overriding the entrypoint. This is the execution command I tried:

docker run \
  -v $(pwd):/data/data/com.termux/files/home/packages \
  -w /data/data/com.termux/files/home/packages \
  --entrypoint sh \
  xeffyr/termux:aarch64 \
  -c ./test.sh

The container is properly started, the system is updated and git is installed. However, mkdir fails with a permission denied error. Upon further inspection, ls -la shows that the bind directory is owned by user radio, instead of system.

See:

permission needed to use chmod +x

Termux on an Android can execute chmod +x without issue, however "Operation is not permitted" occurs when trying the same in either of the docker images.

I have also tried the --privileged command with docker run with the same problem occuring.

Is it possible to provide a action.yml to make it a github action to support build software in termux?

Is it possible to provide a action.yml to make it a github action to support build package in termux?

Such as:

.github/workflow/main.yml:

jobs:
  build-in-termux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: termux/[email protected]
        with:
          platforms: x86_64, aarch64 # all
          run: |
            gcc main.c -o main-{{ platform }}
          output: main-*
      - uses: actions/upload-artifact@v3
        with:
          path: |
            main-*

github actions termux root

name: termux

on:
  workflow_dispatch:

jobs:
  manual_trigger:
    name: test
    runs-on: ubuntu-latest
    container: 
      image: termux/termux-docker:x86_64

    steps:
      - name: update
        run: |
          apt update -y
          apt upgrade -y

when i run this github actions i face this error

Run apt update -y
Ability to run this command as root has been disabled permanently for safety purposes.
Error: Process completed with exit code 1.

Poor Github Actions support

It would be nice if termux-docker supported Github Actions better. Hopefully, people will add Termux to their CI.

I made a test repository to showcase it: guijan/termux-on-gha

The issue is that right now there's no documentation on how to get it working, and the straightforward way is broken. Here's the current state of things:
https://github.com/guijan/termux-on-gha/blob/a9a2cf26be0299c1643be12acfa301b0465ad2c1/.github/workflows/build-and-test.yml
The file is short and commented, hopefully it's easy to follow.

Users need to prefix pkg and pip with the /entrypoint.sh script because otherwise they run as the root user and error. This happens because github overrides the entrypoint, as can be seen here: https://github.com/orgs/community/discussions/26465

If you fix the issue above, you will run into further breakage. The widely used checkout and upload-artifact actions don't currently work with Termux. The checkout action errors because of the same problem as this issue I found out there (no /etc/os-release file, and possibly more): prometheus/prometheus#12656
Someone has suggested adding an /etc/os-release to Termux before: termux/termux-app#2620

I haven't investigated why the upload-artifact action fails.

How to execute binaries of multiple platforms (WIP)

Hi,

First, I want to share a simple test:

  • Configure your machine to work with the multiarch/qemu-user-static.
  • Launch the ARM version of the image with docker run --rm -it termux/termux-docker:aarch64
  • Launch the x86 version of the image with docker run --rm -it termux/termux-docker:latest
  • Then inside the containers, copy from one to another the file /system/bin/busybox in a temporal directory.
  • Try to execute the x86 version in the arm container, and vice versa, inside the temporal directory.

This proof-of-concept demonstrates that inside of the containers you aren't virtualizing the runtime. In fact, you're only virtualizing the processes (binaries). Therefore, you CAN execute binaries of both platforms inside the same container.

This works because the busybox binary is fully static (check it with ldd busybox). The problem begins when you want to execute processes that use shared libraries.

For the Termux libraries, a potential solution exist: using patchelf you can change the rpath to something different. For example, I've planed:

  • /data/data/com.termux/files/usr/lib (native) (the current path)
  • /data/data/com.termux/arm64/usr/lib (aarch64)
  • /data/data/com.termux/arm32/usr/lib (arm)
  • /data/data/com.termux/amd32/usr/lib (i686)
  • /data/data/com.termux/amd64/usr/lib (x86_64)

And copy on these "root" directories (/data/data/com.termux/<pseudo-arch>/) the patched version of the libraries. In my initial tests this should work. And you only need to patch binaries and libraries with: patchelf --set-rpath /data/data/com.termux/amd32/usr/lib --output tool.amd32 tool. Where the original tool binary is from the termux/termux-docker:latest image (so i686). And the tool.amd32 is the patched version that will work in any container.

The problem arrives when you need to handle with the standard bionic libraries at /system/lib<64>/, like libc.so. Is not a problem the ld-android.so library. You can copy it directly to the corresponding target directory (/data/data/com.termux/<pseudo-arch>/usr/lib) because it's fully static. And the binary will use this version. However, for the rest of the libraries (i.e. libc.so, libm.so, libdl.so, etc.) this doesn't work, because they depend of the ld-android.so and others. Therefore when launching the binary the versions of the running (aka emulated) platform in /system/lib<64>/ will be loaded.

The result is that you CAN'T execute any dynamic linking binary. Only static binaries (like busybox).
So my question is: You know how to patch or recompile the bionic libraries to put then on an alternative directory?

My objective is to create a container (mainly for aarch64 arm architecture) with some tools with the x86_64 container. Therefore, I'll have something like: bash and bash.amd64. And I can call to the second to execute the same tool without slow emulation and at native speed. You can extrapolate this to some weighted tools (compilers and linkers?), or any other tool that you call a lot inside a heavy work (compiling?). And in a exceptional cases perhaps you want to remove the "native" (aka emulated) version and replace it with a symbolic link to the "external" (aka native) version.

So, please can you help me solve this problem?
Thank you.

Dynamic DNS resolver

After this is implemented, we have theoratically a working DNS resolver? This would be a cool update that will improve this project greatly.

Edit: This is already discussed in #44. But since it is closed, perhaps we should discuss here.

Hostnames fail to resolve

All hostnames fail to resolve inside the container. I have verified it has connection since I can run curl 1.1.1.1 but trying httpbin.org/ip fails. dnsmasq starts but seems to be stuck since it just eats all of my CPU
image

This was the command used to start the container using docker v24.0.7

docker run -it --rm termux/termux-docker:x86_64

Compile the binaries from source

How did you get the libraries and binaries to make the docker container? Can you provide instructions on how to build them?
I'm really interested in how to compile/obtain the latest development versions of those to make some tests

User specific static-dns-hosts.txt file

Hi,

These containers are very useful. And I have a suggestion to improve them with a small change:

  • Change the "update-static-dns" script (/data/data/com.termux/files/usr/bin/update-static-dns) to read the list of static hosts from two different locations:
    • The regular location /system/etc/static-dns-hosts.txt that represents the common hosts.
    • A new user location like /data/data/com.termux/static-dns-hosts.txt that will be left to the user.
    • Or in the location /system/etc/user-dns-hosts.txt with zero content (what you prefer).

The idea is to start the docker container with a binding of the user file. Then we don't need to replace the hosts decribed inside the image. And at the same time we can add some other hosts. In my case, for example "kernel.org".

You agree?

x86_64: Illegal instruction (core dumped)

$ docker run --rm -it termux/termux-docker:x86_64 
Unable to find image 'termux/termux-docker:x86_64' locally
x86_64: Pulling from termux/termux-docker
3016a7fc27e5: Pull complete 
4f4fb700ef54: Pull complete 
Digest: sha256:64bb0166401db5be679f6ad356903d3cea5c77265df9ac7e0cdfce3c9b21a2e6
Status: Downloaded newer image for termux/termux-docker:x86_64
Illegal instruction (core dumped)
[!] Container is running as non-root, unable to start dnsmasq. DNS will be unavailable.
$ uname -a
Linux ubuntu-pc 5.15.0-71-generic #78-Ubuntu SMP Tue Apr 18 09:00:29 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Haskell pkg config/install

Setting up haskell-regex-base (0.94.0.2) ...
Segmentation fault
dpkg: error processing package haskell-regex-base (--configure):
installed haskell-regex-base package post-installation script subprocess returned error exit status 139
dpkg: dependency problems prevent configuration of haskell-regex-tdfa:
haskell-regex-tdfa depends on haskell-regex-base; however:
Package haskell-regex-base is not configured yet.

dpkg: error processing package haskell-regex-tdfa (--configure):
dependency problems - leaving unconfigured
Errors were encountered while processing:
haskell-regex-base
haskell-regex-tdfa
E: Sub-process /data/data/com.termux/files/usr/bin/dpkg returned an error code (1)

Question: how to use pkg

Hello I tried docker run -it termux/termux-docker:x86_64 but I can't access the network, ping for example fails with are you root? if I start with root entry point I can ping, but I don't want to do that because I can't use pkg

Is there an obvious thing I'm missing?

docker exec issue

sudo docker start termux-x86_64
termux-x86_64
sudo docker exec -it termux-x86_64 /data/data/com.termux/files/usr/bin/login
Error response from daemon: Container a0c723eaa57f6a537c6d9d77c88750ec34eb42b4febb8a40b15eb277a7bd408b is not running

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.