├── docker-search
├── examples
├── speedtest
│ ├── launch
│ └── Dockerfile
├── pandoc
│ ├── launch
│ └── Dockerfile
├── thunderbird
│ ├── launch
│ └── Dockerfile
├── firefox-esr
│ ├── launch
│ └── Dockerfile
└── git
│ ├── Dockerfile
│ └── launch
├── docker
├── docker-machine
├── docker-build
├── docker.build.me
├── docker-compose
├── docker.x11
├── docker-umount
├── docker-run
├── docker.ssh.pipe.cmd
├── docker.ssh.cmd
├── make_dockerfile
├── apt-docker
├── remove_docker_remote.sh
├── LICENSE
├── docker-mount
├── docker.config
├── install_docker_remote.sh
└── README.md
/docker-search:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | docker search --no-trunc "$@"
3 |
--------------------------------------------------------------------------------
/examples/speedtest/launch:
--------------------------------------------------------------------------------
1 | docker run --rm itmaze/speedtest:latest "$@"
2 |
--------------------------------------------------------------------------------
/examples/pandoc/launch:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | docker.x11 itmaze/pandoc:latest "$@"
4 |
--------------------------------------------------------------------------------
/examples/thunderbird/launch:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | docker.x11 itmaze/thunderbird:latest "$@"
4 |
--------------------------------------------------------------------------------
/examples/firefox-esr/launch:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd ~/Downloads
4 |
5 | docker.x11 --ipc=host --shm-size=2g itmaze/firefox-esr:latest --no-remote --sync "$@"
6 |
--------------------------------------------------------------------------------
/docker:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | docker.ssh.cmd -tt docker "$@"
6 |
--------------------------------------------------------------------------------
/docker-machine:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | docker.ssh.cmd -t "$@"
6 |
7 |
--------------------------------------------------------------------------------
/docker-build:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | tar -hzcf - . | docker.ssh.pipe.cmd docker build - "$@"
6 |
--------------------------------------------------------------------------------
/docker.build.me:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | name=$(basename "$(pwd)")
6 | docker-build -t "${local_docker_repo}/${name}" "$@"
7 |
--------------------------------------------------------------------------------
/docker-compose:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | docker-run -v "${remote_docker_socket}":/var/run/docker.sock -it "${remote_docker_container}" compose "$@"
6 |
--------------------------------------------------------------------------------
/docker.x11:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | export script_origin=$(ps -o comm= $PPID)
6 |
7 | docker-run -e DISPLAY -e XAUTHORITY="/home/docker/.Xauthority" -e TZ="${remote_docker_timezone}" --net=host --volume="/home/docker/.Xauthority:/home/docker/.Xauthority:rw" "$@"
8 |
--------------------------------------------------------------------------------
/examples/git/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:stable-slim
2 | LABEL maintainer="onno@itmaze.com.au"
3 |
4 | ARG DEBIAN_FRONTEND=noninteractive
5 |
6 | RUN apt-get update
7 | RUN apt-get -y upgrade
8 | RUN apt-get -y install git
9 |
10 | RUN ln -s $(which git) /usr/local/bin/git
11 |
12 | RUN useradd -ms /bin/bash docker
13 | USER docker
14 |
15 | ENTRYPOINT ["/usr/local/bin/git"]
16 | CMD ["--help"]
17 |
--------------------------------------------------------------------------------
/docker-umount:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | if [ $# -ne 1 ]
6 | then
7 | echo "Usage: '$(basename "$0") volume'"
8 | exit 1
9 | fi
10 |
11 | mountVolume=$1
12 |
13 | dummy=$(docker volume rm "${mountVolume}")
14 |
15 | docker.ssh.cmd fusermount -zu "/home/docker/${mountVolume}"
16 | docker.ssh.cmd rmdir "${mountVolume}"
17 |
18 |
--------------------------------------------------------------------------------
/examples/git/launch:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function remove_volume() {
4 | volumeName=$1
5 | docker-umount ${volumeName} >> /dev/stderr
6 | }
7 |
8 | if type docker-mount &> /dev/null
9 | then
10 | volumeName=$(uuidgen)
11 | trap "remove_volume ${volumeName}" EXIT
12 | docker-mount "${volumeName}" "/home/onno/.ssh" >> /dev/stderr
13 | fi
14 |
15 | docker-run --rm -v${volumeName}:"/home/docker/.ssh" itmaze/git:latest "$@"
16 |
--------------------------------------------------------------------------------
/examples/speedtest/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:stable-slim
2 |
3 | ARG DEBIAN_FRONTEND=noninteractive
4 | ARG server=31363
5 | ENV env_var_name=$server
6 |
7 | RUN apt-get update
8 | RUN apt-get -y upgrade
9 | ADD https://install.speedtest.net/app/cli/install.deb.sh install.deb.sh
10 | RUN bash ./install.deb.sh
11 | RUN apt-get -y install speedtest
12 | RUN /usr/bin/speedtest --accept-license -s $env_var_name
13 |
14 | ENTRYPOINT ["/usr/bin/speedtest"]
15 | CMD ["--help"]
16 |
--------------------------------------------------------------------------------
/examples/thunderbird/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:bullseye-slim
2 |
3 | LABEL maintainer="onno@itmaze.com.au"
4 |
5 | ARG DEBIAN_FRONTEND=noninteractive
6 |
7 | RUN apt-get update
8 | RUN apt-get -y upgrade
9 | RUN apt-get -y install thunderbird
10 | RUN apt-get -y install libcanberra-gtk-module
11 |
12 | RUN ln -s $(which thunderbird) /usr/local/bin/thunderbird
13 |
14 | RUN useradd -ms /bin/bash docker
15 | USER docker
16 |
17 | ENTRYPOINT ["/usr/local/bin/thunderbird"]
18 |
--------------------------------------------------------------------------------
/docker-run:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | volumeName="$(uuidgen)"
6 |
7 | function remove_volume() {
8 | docker-umount "${volumeName}"
9 | }
10 |
11 | if type docker-mount &> /dev/null
12 | then
13 | trap "remove_volume" EXIT
14 | docker-mount "${volumeName}"
15 | docker run --rm -v"${volumeName}":"$(pwd)" -w"$(pwd)" "$@"
16 | else
17 | docker run --rm -v"$(pwd)":"$(pwd)" -w"$(pwd)" "$@"
18 | fi
19 |
--------------------------------------------------------------------------------
/docker.ssh.pipe.cmd:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | declare -a parameters
6 |
7 | while [ "$#" -gt 0 ]
8 | do
9 | if [ "${1:0:1}" == '-' ]
10 | then
11 | parameters+=("$1")
12 | shift
13 | else
14 | break
15 | fi
16 | done
17 |
18 | printf -v remote_command '%q ' "$@"
19 |
20 | /usr/bin/ssh -C -e none -Y -o LogLevel=QUIET -l "${remote_docker_user}" "${parameters[@]}" "${remote_docker_host}" "${remote_command}"
21 |
--------------------------------------------------------------------------------
/examples/pandoc/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:bullseye-slim
2 |
3 | LABEL maintainer="onno@itmaze.com.au"
4 |
5 | ARG DEBIAN_FRONTEND=noninteractive
6 |
7 | RUN apt-get update
8 | RUN apt-get -y upgrade
9 | RUN apt-get -y install pandoc
10 | RUN apt-get -y install texlive-latex-base
11 | RUN apt-get -y install texlive-latex-recommended
12 |
13 | ADD https://github.com/jgm/pandoc/releases/download/3.1.3/pandoc-3.1.3-1-amd64.deb /tmp/pandoc.deb
14 | RUN apt-get -y install /tmp/pandoc.deb
15 |
16 | RUN ln -s $(which pandoc) /usr/local/bin/pandoc
17 |
18 | RUN useradd -ms /bin/bash docker
19 | USER docker
20 |
21 | ENTRYPOINT ["/usr/local/bin/pandoc"]
22 | CMD ["--help"]
23 |
--------------------------------------------------------------------------------
/docker.ssh.cmd:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | declare -a parameters
6 |
7 | while [ "$#" -gt 0 ]
8 | do
9 | if [ "${1:0:1}" == '-' ]
10 | then
11 | parameters+=("$1")
12 | shift
13 | else
14 | break
15 | fi
16 | done
17 |
18 | printf -v remote_command '%q ' "$@"
19 |
20 | # Source: https://scripter.co/nim-check-if-stdin-stdout-are-associated-with-terminal-or-pipe/
21 | if [[ -t 0 ]]
22 | then
23 | # terminal
24 | interactive_tty=""
25 | else
26 | # pipe
27 | interactive_tty="-n"
28 | fi
29 |
30 | if [[ -v DEBUG ]]
31 | then
32 | logging=("-v")
33 | else
34 | logging=("-o" "LogLevel=QUIET")
35 | fi
36 |
37 | /usr/bin/ssh ${interactive_tty} -C -e none -Y "${logging[@]}" -l "${remote_docker_user}" "${parameters[@]}" "${remote_docker_host}" "${remote_command}"
38 |
--------------------------------------------------------------------------------
/make_dockerfile:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | container=$(basename "$(pwd)")
6 |
7 | if [ $# -eq 1 ]
8 | then
9 | executable="$1"
10 | else
11 | executable="${container}"
12 | fi
13 |
14 | cat <<-EOF > Dockerfile
15 | FROM debian:stable-slim
16 |
17 | LABEL maintainer="${local_docker_maintainer}"
18 |
19 | ARG DEBIAN_FRONTEND=noninteractive
20 |
21 | RUN apt-get update
22 | RUN apt-get -y upgrade
23 | RUN apt-get -y install ${container}
24 |
25 | RUN ln -s \$(which ${executable}) /usr/local/bin/${executable}
26 |
27 | RUN useradd -ms /bin/bash docker
28 | USER docker
29 |
30 | ENTRYPOINT ["/usr/local/bin/${executable}"]
31 | CMD ["--help"]
32 | EOF
33 |
34 | cat <<-EOF > launch
35 | #!/bin/bash
36 |
37 | docker.x11 "${local_docker_repo}/${container}:latest" "\$@"
38 | EOF
39 | chmod +x launch
40 |
--------------------------------------------------------------------------------
/apt-docker:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | if [ $# -eq 2 ]
6 | then
7 | container="$1"
8 | executable="$2"
9 | else
10 | container="$1"
11 | executable="${container}"
12 | fi
13 |
14 | if [ -d "${local_docker_home}/${local_docker_repo}/${container}" ]
15 | then
16 | echo "Error: '${local_docker_home}/${local_docker_repo}/${container}' already exists, aborting."
17 | exit 1
18 | fi
19 |
20 | if [ -e "${local_bin_dir}/${executable}" ]
21 | then
22 | echo "Error: '${local_bin_dir}/${executable}' already exists, aborting."
23 | exit 1
24 | fi
25 |
26 | mkdir -p "${local_docker_home}/${local_docker_repo}/${container}"
27 | (
28 | cd "${local_docker_home}/${local_docker_repo}/${container}" || exit
29 | make_dockerfile "${executable}"
30 | docker-build -t "${local_docker_repo}/${container}"
31 | ln -s "${local_docker_home}/${local_docker_repo}/${container}/launch" "${local_bin_dir}/${executable}"
32 | )
33 |
34 |
--------------------------------------------------------------------------------
/remove_docker_remote.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | # This will uninstall this project from the user default bin directory.
6 |
7 | function remove_link () {
8 | # Remove a symlink (or file if it's the same as the source)
9 |
10 | sourceFile="$(readlink -f "$1")"
11 | targetFile="${local_bin_dir}/$(basename "$1")"
12 |
13 | if [ "${targetFile}" == "${sourceFile}" ]
14 | then
15 | note "Warning: '${targetFile}' and '${sourceFile}' are the same file, '${targetFile}' was not removed."
16 | return 1
17 | fi
18 |
19 | if diff -q "${sourceFile}" "${targetFile}"
20 | then
21 | rm "${targetFile}"
22 | return 0
23 | fi
24 | note "Warning: '${targetFile}' and '${sourceFile}' differ, '${targetFile}' was not removed."
25 | }
26 |
27 | while read -r sourceFile <&3
28 | do
29 | remove_link "${sourceFile}"
30 | done 3< <(
31 | find "${local_config_dir}" \
32 | -maxdepth 1 \
33 | -type f \
34 | -executable \
35 | ! -name '*.sh'
36 | )
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Onno Benschop, ITmaze
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/docker-mount:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | if [ $# -eq 1 ]
6 | then
7 | mountVolume=$1
8 | mountPath=$(pwd)
9 | elif [ $# -ne 2 ]
10 | then
11 | echo "Usage: '$(basename "$0") volume [path]'"
12 | exit 1
13 | else
14 | mountVolume=$1
15 | mountPath=$2
16 | fi
17 |
18 | if docker volume list -q | fromdos | grep -q ^"${mountVolume}"$
19 | then
20 | echo "Warning: Volume exists: ${mountVolume}, skipped."
21 | exit 1
22 | fi
23 |
24 | me=$(whoami)
25 | myIP=$(hostname -I | cut -d ' ' -f1)
26 |
27 | docker.ssh.cmd mkdir -p "${mountVolume}"
28 |
29 | docker.ssh.cmd /usr/bin/sshfs \
30 | -o reconnect \
31 | -o ServerAliveInterval=15 \
32 | -o ServerAliveCountMax=3 \
33 | -o UserKnownHostsFile=/dev/null \
34 | -o allow_other \
35 | -o StrictHostKeyChecking=no \
36 | -o auto_unmount \
37 | -o uid=0 \
38 | -o gid=0 \
39 | -o idmap=user \
40 | "${me}@${myIP}":"${mountPath}" "${mountVolume}"
41 |
42 | dummy=$(docker volume create --name "${mountVolume}" -o type=none -o device="/home/docker/${mountVolume}" -o o=bind --label sshfs=yes --label host="${me}@${myIP}" --label path="${mountPath}" --label script_origin="${script_origin}")
43 |
--------------------------------------------------------------------------------
/docker.config:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [[ -v DEBUG ]]
3 | then
4 | set -x
5 | set -o xtrace
6 | set -v
7 | fi
8 |
9 | # Update these variables to suit your set-up
10 |
11 | # Used to store symbolic links to containers built with apt-docker.
12 | local_bin_dir=~/bin
13 |
14 | # Used to store the repository directory
15 | local_docker_home=~/docker
16 |
17 | # Used to store the local repository of conainters
18 | local_docker_repo="$(hostname)"
19 |
20 | # Used in a Dockerfile generated by apt-docker
21 | local_docker_maintainer="$(whoami)@$(hostname -A)"
22 |
23 | # Used to run actual docker commands over ssh
24 | remote_docker_host="docker.local"
25 | remote_docker_user="docker"
26 | remote_docker_timezone="${TZ:Etc/UTC}"
27 |
28 | # Docker socket
29 | remote_docker_container=docker.io/library/docker:latest
30 | remote_docker_socket=/var/run/docker.sock
31 |
32 | function note () {
33 | echo "$@" | fold -s -w $(tput cols)
34 | }
35 |
36 | function stop () {
37 | note "$@"
38 | exit 1
39 | }
40 |
41 | function checkDir () {
42 | if [ ! -d "$1" ]
43 | then
44 | stop "The directory '$1' does not exist, check your remote-docker configuration at '${BASH_SOURCE[0]}', aborting."
45 | fi
46 | }
47 |
48 | checkDir "${local_bin_dir}"
49 | checkDir "${local_docker_home}/${local_docker_repo}"
50 |
51 |
--------------------------------------------------------------------------------
/install_docker_remote.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | local_config_dir="$(dirname "$(readlink -f "$0")")"
3 | source "${local_config_dir}/docker.config"
4 |
5 | # This will prompt the user to install symbolic links pointing at this project
6 | # in their default bin directory (~/bin)
7 |
8 | response='No'
9 |
10 | function default_prompt_string () {
11 | # Based on previous user response, show that as the default in square brackets.
12 |
13 | previous_response="${1^^}"
14 |
15 | for word in 'Yes' 'No' 'All'
16 | do
17 | if [[ "${previous_response:0:1}" == "${word:0:1}" ]]
18 | then
19 | echo -n "[${word}]"
20 | else
21 | echo -n "${word}"
22 | fi
23 | echo -n '/'
24 | done
25 | echo -n 'Cancel'
26 | }
27 |
28 | function ask_to_make_symlink () {
29 | # Ask the user if they want to install a symlink
30 |
31 | default_response="${response}"
32 |
33 | while true
34 | do
35 | read -rp "Install link ($(default_prompt_string "${response}")):" response
36 | response="${response:-$default_response}"
37 |
38 | case "${response:0:1}" in
39 | y|Y )
40 | response='Yes'
41 | return 0
42 | ;;
43 | a|A )
44 | response='All'
45 | return 0
46 | ;;
47 | n|N )
48 | response='No'
49 | return 1
50 | ;;
51 | c|C )
52 | exit 1
53 | ;;
54 | * )
55 | response="${default_response}"
56 | ;;
57 | esac
58 | done
59 | }
60 |
61 | function install_link () {
62 | # Install a symlink in the user's configured bin directory
63 |
64 | sourceFile="$(readlink -f "$1")"
65 | targetFile="${local_bin_dir}/$(basename "$1")"
66 |
67 | if [[ "$(readlink -f "${sourceFile}")" == "$(readlink -f "${targetFile}")" ]]
68 | then
69 | # Nothing to do
70 | return 0
71 | fi
72 |
73 | if [[ -L "${targetFile}" && -e "${targetFile}" ]]
74 | then
75 | alert="Warning: symbolic link '${targetFile}' exists and is pointing to a file."
76 | elif [[ -L "${targetFile}" && ! -e "${targetFile}" ]]
77 | then
78 | alert="Warning: broken symbolic link '${targetFile}' exists."
79 | elif [[ -f "${targetFile}" ]]
80 | then
81 | alert="Warning: file '${targetFile}' exists."
82 | else
83 | alert=""
84 | fi
85 |
86 | if [ "${response}" != 'All' ] && [ -n "${alert}" ]
87 | then
88 | note "${alert}"
89 | note "This will replace '${targetFile}' with a symbolic link to '${sourceFile}'?"
90 | if ! ask_to_make_symlink
91 | then
92 | return 99
93 | fi
94 | fi
95 |
96 | ln -sf "${sourceFile}" "${targetFile}"
97 | }
98 |
99 | while read -r sourceFile <&3
100 | do
101 | install_link "${sourceFile}"
102 | done 3< <(
103 | find "${local_config_dir}" -maxdepth 1 \
104 | -type f \
105 | -executable \
106 | ! -name '*.sh'
107 | )
108 |
--------------------------------------------------------------------------------
/examples/firefox-esr/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:stable-slim
2 |
3 | ARG DEBIAN_FRONTEND=noninteractive
4 |
5 | RUN apt-get update
6 | RUN apt-get -y upgrade
7 | RUN apt-get -y install \
8 | firefox-esr \
9 | firefox-esr-l10n-en-gb \
10 | fonts-wqy-microhei \
11 | hunspell-en-au \
12 | hunspell-en-gb \
13 | hyphen-en-gb \
14 | libcanberra-gtk3-module \
15 | libcanberra-gtk-module \
16 | libegl1 \
17 | libpci3 \
18 | webext-ublock-origin \
19 | xterm
20 |
21 | RUN echo >> /etc/firefox-esr/firefox-esr.js
22 | RUN echo '// Set local preferences from Dockerfile' >> /etc/firefox-esr/firefox-esr.js
23 | RUN echo 'pref("app.normandy.first_run", false);' >> /etc/firefox-esr/firefox-esr.js
24 | RUN echo 'pref("browser.warnOnQuit", false);' >> /etc/firefox-esr/firefox-esr.js
25 | RUN echo 'pref("browser.startup.homepage", "about:blank");' >> /etc/firefox-esr/firefox-esr.js
26 | RUN echo 'pref("datareporting.policy.firstRunURL", "");' >> /etc/firefox-esr/firefox-esr.js
27 | RUN echo 'pref("app.update.enabled", false);' >> /etc/firefox-esr/firefox-esr.js
28 | RUN echo 'pref("app.update.auto", false);' >> /etc/firefox-esr/firefox-esr.js
29 | RUN echo 'pref("toolkit.cosmeticAnimations.enabled", false);' >> /etc/firefox-esr/firefox-esr.js
30 | RUN echo 'pref("toolkit.scrollbox.smoothScroll", false);' >> /etc/firefox-esr/firefox-esr.js
31 | RUN echo 'pref("image.animation_mode", "none");' >> /etc/firefox-esr/firefox-esr.js
32 | RUN echo 'pref("browser.startup.homepage_override.mstone", "ignore");' >> /etc/firefox-esr/firefox-esr.js
33 | RUN echo 'pref("intl.accept_languages","en-GB");' >> /etc/firefox-esr/firefox-esr.js
34 | RUN echo 'pref("intl.locale.requested","en-GB");' >> /etc/firefox-esr/firefox-esr.js
35 | RUN echo 'pref("ui.prefersReducedMotion", 1);' >> /etc/firefox-esr/firefox-esr.js
36 | RUN echo 'pref("toolkit.cosmeticAnimations.enabled", false);' >> /etc/firefox-esr/firefox-esr.js
37 | RUN echo 'pref("geo.enabled", false);' >> /etc/firefox-esr/firefox-esr.js
38 | RUN echo 'pref("datareporting.policy.dataSubmissionEnabled", false);' >> /etc/firefox-esr/firefox-esr.js
39 | RUN echo 'pref("toolkit.telemetry.unified", false);' >> /etc/firefox-esr/firefox-esr.js
40 | RUN echo 'pref("toolkit.telemetry.enabled", false);' >> /etc/firefox-esr/firefox-esr.js
41 | RUN echo 'pref("toolkit.telemetry.reportingpolicy.firstRun", false);' >> /etc/firefox-esr/firefox-esr.js
42 | RUN echo 'pref("datareporting.healthreport.uploadEnabled", false);' >> /etc/firefox-esr/firefox-esr.js
43 | RUN echo 'pref("toolkit.telemetry.server", "");' >> /etc/firefox-esr/firefox-esr.js
44 |
45 | RUN echo 'LANG="en_AU.UTF-8"' > /etc/default/locale
46 | RUN echo 'LANGUAGE="en_AU:en" ' >> /etc/default/locale
47 |
48 | RUN useradd -ms /bin/bash docker
49 |
50 | RUN ln -s /home/onno/Downloads/ /home/docker/Downloads
51 |
52 | USER docker
53 |
54 | ENTRYPOINT ["/usr/bin/firefox-esr"]
55 | CMD ["https://www.ecosia.org/"]
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Remote Docker
2 |
3 | This project uses Docker to create an environment where you can run containers on a remote host, in such a way that your local working directory is visible to the container and optionally use X11 to use a GUI.
4 |
5 | This allows you to for example launch Firefox inside a Docker container, using your local ~/Downloads directory, but without access to the rest of your file-system.
6 |
7 | You can use this same system to run the latest version of git - when for example your copy of openssh is out of date and github updates the formats of keys - again, or use apt to install an application as a Docker container, or trial some new source without impacting your local environment.
8 |
9 | If you want to run a specific version of Python, you can do that without needing to install it locally.
10 |
11 | This uses fuse sshfs to reverse mount the file-system (from the *docker-machine* to your *workstation*), create a docker-volume, then mount that on the container with the working directory set to the mount and taking care of UID and GID.
12 |
13 |
14 | # Terms and Assumptions
15 |
16 | The term *workstation* refers to your "local" environment, where your files live, where you search the web and do your work.
17 |
18 | The term *docker-machine* represents a "remote" environment, accessible via ssh that has Docker installed. I use a minimal Debian install, but it could be anything accessible via `ssh`.
19 |
20 | The *docker-machine* is by default called "docker.local" and can be connected to by the local user as "docker@docker.local". Similarly, the *workstation* can be resolved by its hostname from the *docker-machine* and you can connect to your username from the *docker-machine* to the *workstation*.
21 |
22 | Authentication via ssh must be passwordless - in *both* directions, use `ssh-copy-id` to set it up.
23 |
24 | The scripts in this project are written in `bash` and are expected to remain together in a single directory, typically the directory where you have cloned this repository. The `docker.config` file is required and you should edit it before installation.
25 |
26 |
27 | # How it works
28 |
29 | The underlying logic does not depend on a local installation of Docker. It uses `ssh` to run Docker commands on the remote host. The point of this is that it could run across the Internet, not just to a VM like I'm using it today.
30 |
31 | To share files between the Docker container and the local file-system, these scripts use `docker-mount` and `docker-umount` commands. These commands mount a local directory to a remote directory so it can be used as a Docker volume inside the container. This is achieved in several steps:
32 |
33 | 1. Connect to the *docker-machine* over ssh.
34 | 2. Create a unique empty directory (using uuidgen).
35 | 3. Use sshfs from the *docker-machine* to the *workstation* to mount the local directory to the new unique remote directory.
36 | 4. Create a Docker volume of that mounted directory.
37 | 5. Start a container with that Docker volume.
38 |
39 | The `docker-umount` does the reverse, removing the volume, un-mounting the sshfs mount, removing the directory.
40 |
41 |
42 | # Usage
43 |
44 | You should be able to run the `docker` command as if Docker is installed on your local machine and have it execute remotely. The `docker.x11` command should act as-if you launched an X11 application on your local machine. The `docker-run` command will mount the current directory inside the container and set the working directory to that same path.
45 |
46 | Use this by putting all these scripts in ~/bin. On the *workstation*, it uses ~/docker/{hostname}/ to store any containers built with `apt-docker`. All images built using this are tagged by default as {hostname}/{xyz}:latest. The "default" maintainer for such images are set to {login}@{hostname}. If you do upload any images, you should probably update the email address (and the tag). These values can be updated in the `docker.config` file.
47 |
48 | You can create more than one mount and use more than one volume in the same container at the same time. This is useful if you want to run the aws-cli or git command and provide access to ~/.ssh or ~/.aws as well as the current directory.
49 |
50 |
51 | # Scripts
52 |
53 | The commands are:
54 |
55 | - `docker`, runs Docker commands across ssh on the *docker-machine*.
56 | - `docker-run`, implements the `docker run` command by connecting the current directory to a Docker volume and then adding the volume mount to the `docker run` command. Uses `docker-mount` and `docker-umount`.
57 | - `docker-mount`, creates a unique directory on the *docker-machine* to use as a mount point for sshfs. Mounts the current *workstation* directory via sshfs, and creates a Docker volume from that mount. Uses `uuidgen`.
58 | - `docker-umount`, removes the Docker volume, un-mounts sshfs, removes the directory on the *docker-machine*.
59 | - `docker.x11`, uses ssh x-forwarding to get the X11 packets between the *docker-machine* and the *workstation*. __Security Warning__, this uses `--net=host`
60 | - `apt-docker`, attempts to create a minimal container that installs a single Debian application in a debian:stable-slim container and then creates a symlink between the container and your local ~/bin directory, making it look like you just installed an application locally. This command refuses to run if the container directory or symbolic link already exists.
61 | - `make_dockerfile`, create a minimal Dockerfile and launch command, used by `apt-docker`.
62 | - `docker-build`, implements `docker build`, using a tar file of the current directory, sent over ssh to the build command running on the *docker-machine*.
63 | - `docker.build.me`, build the current directory as a container, tagged with the directory name. Uses `docker-build`.
64 | - `docker-compose`, the local directory is mounted on the *docker-machine* and the docker-compose command is run inside that directory. Please read the docker-compose caveats below. Uses `docker-mount` and `docker-umount`.
65 | - `docker-machine`, execute `docker-machine` commands on the *docker-machine*.
66 | - `docker-search`, run `docker search --no-trunc` on the *docker-machine*.
67 | - `docker.ssh.cmd`, the underlying ssh command that actually sends the docker commands to the *docker-machine*. You can edit the 'userName' and 'hostName' variables here.
68 |
69 |
70 | # How to install (and uninstall)
71 |
72 | - `git clone https://github.com/ITmaze/remote-docker.git`
73 | - `cd remote-docker`
74 | - `vi docker.config`
75 | - `./install_docker_remote.sh`
76 |
77 | ## Notes on installation:
78 |
79 | - `docker.config` is requried and is expected to be located with all the other scripts. It's used by all commands.
80 | - `install_docker_remote.sh` creates symbolic links between the configured "bin" directory (by default "~/bin") and each of the scripts.
81 | - `remove_docker_remote.sh` removes the project from the configured "bin" directory. It will only do so if the files are either identical, or symbolic links to the script with the same name.
82 |
83 |
84 | # Docker-Compose Caveats
85 |
86 | This is a re-written version using the official Docker `docker.io/library/docker:latest` image which includes the `compose` plug-in. When you run it for the first time, it will pull the image, then launch. If you use the default image, you can refresh it using:
87 |
88 | - `docker pull docker`
89 |
90 | To operate, `docker-compose` maps the Docker socket on the *docker-machine* (by default `/var/run/docker.sock`) inside the `docker` container, where it then executes the `compose` sub-command using the parameters supplied.
91 |
92 | Note: This has not been thoroughly tested yet and the `stdout` output is a little mangled, patches welcome.
93 |
94 |
95 | # Requirements
96 |
97 | There are requirements for both the *docker-machine* and the *workstation*. These are different.
98 |
99 | One thing both have in common is that you need to be able to ssh between both without using a password. `ssh-copy-id` is the way to make that happen. If you get an error about missing an identity, create one using `ssh-keygen`. This is required, since we're using ssh from the *workstation* to the *docker-machine* to execute Docker commands and we're using ssh from the *docker-machine* to the *workstation* to mount a directory using sshfs.
100 |
101 | ## Workstation requirements:
102 |
103 | - ssh
104 | - sshd
105 | - uuidgen (uuid-runtime)
106 | - fromdos (tofrodos)
107 |
108 | ## Docker-Machine requirements:
109 |
110 | - docker
111 | - ssh
112 | - sshd
113 | - sshfs
114 | - write permission on the home directory of the docker user
115 |
116 |
117 | # Examples
118 |
119 | The examples directory shows some of the ways that this tool can be used. It is incomplete and as I go through my existing use of this code (70+ containers), the example directory will likely grow.
120 |
121 | To use a container, I add a symlink between my ~/bin and a launch file. For example: ~/bin/speedtest -> ./examples/speedtest/launch. Note, the `apt-docker` command creates this symbolic link automatically when you build a container with it.
122 |
123 | - __firefox-esr__, runs firefox across X11, linking the /home/docker/Downloads directory to the /home/onno/Downloads directory, so that the mount point inside the container has the same path as my actual ~/Downloads directory. Update the username to reflect your own user.
124 | - __git__, runs git in the current directory, but mounts the ~/.ssh directory so it can access your keys.
125 | - __speedtest__, simple example of running a docker command without any volume mounting.
126 |
127 |
128 | # Bugs and potential Security Issues
129 |
130 | - An sshfs mount exists while a container is running. Anyone with access to the *docker-machine* also has full access to all the sshfs mounts.
131 | - There are times when `docker-volume` volumes do not un-mount cleanly, root cause to be determined, but likely interrupted launch of a command. Note that these volumes don't actually take up any disk-space, since they're sshfs mounts from the *docker-machine* to the *workstation*. You can remove such a mount using `docker-umount {volumeName}`, but note that you can only use one {volumeName} at a time.
132 | - Fixed: 58546e7 The quote handling isn't clean, sometimes double quoting is required. This appears to be an ssh *feature*. Using a git container to commit for example requires some shenanigans: `git commit -m "'Initial commit.'"`
133 | - Fixed: 909ba1e Note that currently the console displays "Creating volume:" and "Removing volume:" messages. If you know how to make those go away, please provide a patch. (Yes, I'm aware that I'm echoing those strings, it's the volume id from Docker that really needs hiding that I cannot control.)
134 |
135 |
136 | # Kittens Clause
137 |
138 | - Fair warning: This isn't feature complete and probably kills kittens.
139 | - Until a few days ago this was a set of scripts on my workstation. Today it's a github project. If you break it, you get to keep both parts.
140 | - Naming isn't consistent.
141 | - There are times when a command doesn't "come back", likely the Docker console is "helping". You can kill the Docker container from another shell using `docker ps` and `docker kill`.
142 | - I have tested this on a bare machine to ensure that it should work for you out of the box, but it might not. If it doesn't please file an issue and I'll have a look.
143 | - Feel free to get in touch, but if you want to fix something or suggest a feature, please create an issue or supply a patch.
144 | - This was inspired by the pioneering hard work by [Jess Frazelle](https://github.com/jessfraz) who introduced me to the idea of running everything inside Docker. My workstation isn't quite there yet, but it's getting closer every day.
145 | - I blame [Corey Quinn](https://www.lastweekinaws.com/t/) for asking silly questions and my mother for teaching me not to keep my big mouth shut - enjoy!
146 |
--------------------------------------------------------------------------------