Skip to content

Instantly share code, notes, and snippets.

@drdaeman
Last active January 19, 2022 10:28
Show Gist options
  • Save drdaeman/84f10a7b9da9d2fe152e36b426bde00d to your computer and use it in GitHub Desktop.
Save drdaeman/84f10a7b9da9d2fe152e36b426bde00d to your computer and use it in GitHub Desktop.

Revisions

  1. drdaeman revised this gist Apr 24, 2017. 1 changed file with 57 additions and 0 deletions.
    57 changes: 57 additions & 0 deletions rkt-on-wsl-c767336b.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    diff --git a/pkg/mountinfo/mountinfo.go b/pkg/mountinfo/mountinfo.go
    index f227902..557bb36 100644
    --- a/pkg/mountinfo/mountinfo.go
    +++ b/pkg/mountinfo/mountinfo.go
    @@ -20,7 +20,6 @@ import (
    "fmt"
    "io"
    "os"
    - "sort"
    "strconv"
    "strings"

    @@ -50,7 +49,6 @@ func ParseMounts(pid uint) (Mounts, error) {
    return nil, err
    }
    defer mi.Close()
    -
    return parseMountinfo(mi)
    }

    @@ -136,6 +134,5 @@ func parseMountinfo(mi io.Reader) (Mounts, error) {
    if err := sc.Err(); err != nil {
    return nil, errwrap.Wrap(errors.New("problem parsing mountinfo"), err)
    }
    - sort.Sort(podMounts)
    return podMounts, nil
    }
    diff --git a/pkg/sys/sys_linux.go b/pkg/sys/sys_linux.go
    index f273826..4b4b3f5 100644
    --- a/pkg/sys/sys_linux.go
    +++ b/pkg/sys/sys_linux.go
    @@ -19,6 +19,10 @@ import "syscall"
    func Syncfs(fd int) error {
    _, _, err := syscall.RawSyscall(SYS_SYNCFS, uintptr(fd), 0, 0)
    if err != 0 {
    + if err == syscall.ENOSYS {
    + // Let it fail
    + return nil
    + }
    return syscall.Errno(err)
    }
    return nil
    diff --git a/stage1_fly/run/main.go b/stage1_fly/run/main.go
    index e3ac294..620d5ce 100644
    --- a/stage1_fly/run/main.go
    +++ b/stage1_fly/run/main.go
    @@ -434,7 +434,9 @@ func stage1(rp *stage1commontypes.RuntimePod) int {

    if err := mounter.Mount(mount.HostPath, absTargetPath, mount.Fs, mount.Flags, ""); err != nil {
    log.PrintE(fmt.Sprintf("can't mount %q on %q with flags %v", mount.HostPath, absTargetPath, mount.Flags), err)
    - return 254
    + if mount.HostPath != "" || mount.Flags != (syscall.MS_REC | syscall.MS_SHARED) {
    + return 254
    + }
    }
    }

  2. drdaeman created this gist Apr 24, 2017.
    179 changes: 179 additions & 0 deletions rkt-fly-on-wsl.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,179 @@
    Just a heads up for those who are looking into running Docker containers *natively* on WSL.
    While it's not usable for anything serious (even your toy project development), there is a way.

    Nuances:

    - We'll be using rkt and not Docker. So, no docker-compose for you.
    - There will be some source code patching. Nothing serious, just a few lines.
    - Very limited isolation and networking capabilities. Think of always `--privileged`, `--net-host` and no DNS.

    WSL doesn't have cgroups at the moment, and probably won't have them anytime soon, so no way Docker would work.
    Unless you know a trick to replace `runc`/`containerd` with something.

    However, rkt has a ["rkt fly"](https://coreos.com/rkt/docs/latest/running-fly-stage1.html) feature that
    uses simple chroot environments.

    Here's what I did:

    1. Installed Go 1.8.1 using godeb (I was using older 14.04 OS image).
    I guess `apt-get install golang` should also work, but not sure.

    2. Checked out rkt git repository: `git clone https://github.com/rkt/rkt.git` and `cd rkt`

    3. Installed necessary build dependencies with `apt-get install autoconf build-essential libacl1-dev realpath`

    4. There are few issues that prevent rkt from just running. I've patched the following files:

    - In `pkg/sys/sys_linux.go` in `func Syncfs(int) error` there is a `SYS_SYNCFS` syscall that is not implemented in WSL. Let's ignore `ENOSYS`:

    if err != 0 {
    + if err == syscall.ENOSYS {
    + return nil
    + }
    return syscall.Errno(err)
    }

    - In `stage1_fly/run/main.go` there will be some mounting failures. WSL seem to fail when host path is an empty string:

    if err := mounter.Mount(mount.HostPath, absTargetPath, mount.Fs, mount.Flags, ""); err != nil {
    log.PrintE(fmt.Sprintf("can't mount %q on %q with flags %v", mount.HostPath, absTargetPath, mount.Flags), err)
    - return 254
    + if mount.HostPath != "" || mount.Flags != (syscall.MS_REC | syscall.MS_SHARED) {
    + return 254
    + }
    }
    }

    - And I've had to patch `pkg/mountinfo/mountinfo.go`, removing `sort.Sort(podMounts)` line completely,
    and a `"sort"` import line (since sort isn't used anywhere else). I don't know why this was necessary, and too lazy to debug,
    but rkt stage1 `run` binary just hang otherwise, after `read` call, not yet calling `close`.
    I don't think rkt actually relies on results' ordering, anyway.

    5. With those modifications I was able to [build rkt normally](https://github.com/rkt/rkt/blob/master/Documentation/hacking.md#building-rkt):

    ./autogen.sh && ./configure --with-stage1-flavors=fly --disable-tpm --disable-sdjournal && make

    6. Then I was able to run a container. Here is a normal `rkt run` invocation:

    $ sudo ./build-rkt-1.25.0+git/target/bin/rkt run --interactive --insecure-options=image docker://hello-world:latest
    Downloading sha256:78445dd4522 [=================================] 971 B / 971 B
    run: disabling overlay support: "overlay entry not present in /proc/filesystems"
    run: can't mount "" on "/dev" with flags 1064960: invalid argument
    run: can't mount "" on "/proc" with flags 1064960: invalid argument
    run: can't mount "" on "/sys" with flags 1064960: invalid argument

    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    ...

    7. There is a clean-up problem, though - when a pod (container) exists, mounted directories (dev, proc, sys and tmp) aren't unmounted. I haven't yet figured why, but I've had to run the following:

    grep -F pods/run /proc/mounts | awk '{ print $2 }' | sort --reverse | xargs -I '{}' sudo umount '{}'

    (Put pod ID after `pods/run`, e.g. `pods/run/8ae2ec64` to target a specific pod only - this is important if you have some pods still running. The reverse sorting is important, because there are some nested mounts.)

    After this, pod can be garbage collected:

    $ sudo ./build-rkt-1.25.0+git/target/bin/rkt gc --grace-period=1s
    Garbage collecting pod "8ae2ec64-69fe-412a-a9f4-8e4aabd06405"

    8. Empty volumes (`kind=empty`) are broken as well, probably because of same no-empty-source limitation. Only `kind=host` seem to work.

    Of course, this is very fragile and extremely limited. But... it works! Well, sort of.

    Here's a more realistic example:

    $ sudo ./build-rkt-1.25.0+git/target/bin/rkt run --interactive \
    > --volume=volume-var-lib-postgresql-data,kind=host,source=$HOME/tmp \
    > --insecure-options=image docker://postgres:latest
    run: disabling overlay support: "overlay entry not present in /proc/filesystems"
    run: can't mount "" on "/dev" with flags 1064960: invalid argument
    run: ignoring this mount issue
    run: can't mount "" on "/proc" with flags 1064960: invalid argument
    run: ignoring this mount issue
    run: can't mount "" on "/sys" with flags 1064960: invalid argument
    run: ignoring this mount issue
    The files belonging to this database system will be owned by user "postgres".
    This user must also own the server process.

    The database cluster will be initialized with locale "en_US.utf8".
    The default database encoding has accordingly been set to "UTF8".
    The default text search configuration will be set to "english".

    Data page checksums are disabled.

    fixing permissions on existing directory /var/lib/postgresql/data ... ok
    creating subdirectories ... ok
    selecting default max_connections ... 100
    selecting default shared_buffers ... 128MB
    selecting dynamic shared memory implementation ... sysv
    creating configuration files ... ok
    running bootstrap script ... ok
    performing post-bootstrap initialization ... ok
    syncing data to disk ... ok

    WARNING: enabling "trust" authentication for local connections
    You can change this by editing pg_hba.conf or using the option -A, or
    --auth-local and --auth-host, the next time you run initdb.

    Success. You can now start the database server using:

    pg_ctl -D /var/lib/postgresql/data -l logfile start

    ****************************************************
    WARNING: No password has been set for the database.
    This will allow anyone with access to the
    Postgres port to access your database. In
    Docker's default configuration, this is
    effectively any other container on the same
    system.

    Use "-e POSTGRES_PASSWORD=password" to set
    it in "docker run".
    ****************************************************
    waiting for server to start....LOG: database system was shut down at 2017-04-24 23:25:02 UTC
    LOG: MultiXact member wraparound protections are now enabled
    LOG: autovacuum launcher started
    LOG: database system is ready to accept connections
    done
    server started
    ALTER ROLE


    /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*

    LOG: received fast shutdown request
    LOG: aborting any active transactions
    LOG: autovacuum launcher shutting down
    waiting for server to shut down....LOG: shutting down
    WARNING: could not flush dirty data: Function not implemented
    WARNING: could not flush dirty data: Function not implemented
    LOG: database system is shut down
    done
    server stopped

    PostgreSQL init process complete; ready for start up.

    LOG: database system was shut down at 2017-04-24 23:25:05 UTC
    LOG: MultiXact member wraparound protections are now enabled
    LOG: autovacuum launcher started
    LOG: database system is ready to accept connections

    (For some reason, it took a good minute to start, while using CPU a lot.
    I think Docker in VirtualBox is much faster and less CPU-intensive.)

    And in another WSL console window:

    $ psql -h 127.0.0.1 -p 5432 -U postgres
    psql (9.3.16, server 9.6.2)
    WARNING: psql major version 9.3, server major version 9.6.
    Some psql features might not work.
    Type "help" for help.

    postgres=# SELECT version();
    version
    ------------------------------------------------------------------------------------------
    PostgreSQL 9.6.2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
    (1 row)

    :-)