Jump to content

Docker: Difference between revisions

From 太極
Brb (talk | contribs)
Brb (talk | contribs)
 
(496 intermediate revisions by the same user not shown)
Line 15: Line 15:


== Containers vs virtual machines ==
== Containers vs virtual machines ==
* [https://www.howtogeek.com/docker-vs-virtual-machines-whats-best-for-your-homelab/ Docker vs. Virtual Machines What’s Best for Your Homelab?]
* Differences: https://youtu.be/BFKNwr_wllc
* Differences: https://youtu.be/BFKNwr_wllc
* Work together: https://youtu.be/BFKNwr_wllc
* Work together: https://youtu.be/BFKNwr_wllc
=== KubeVirt ===
* [https://kubevirt.io/ KubeVirt] brings VMs into containerized workflows by converting the VMs into containers, where they run with the benefits of containerized applications. [https://opensource.com/article/20/12/containers-101 6 container concepts you need to understand]


== OS containers vs application containers ==
== OS containers vs application containers ==
Line 32: Line 36:


== Ubuntu x86 and Mint ==
== Ubuntu x86 and Mint ==
* https://docs.docker.com/install/linux/docker-ce/ubuntu/
<ul>
* [https://www.howtoforge.com/tutorial/how-to-install-kubernetes-on-ubuntu/ How to Install and Configure Kubernetes and Docker on Ubuntu 18.04 LTS]
<li>https://docs.docker.com/install/linux/docker-ce/ubuntu/
 
{{Pre}}
<syntaxhighlight lang='bash'>
# Uninstall old versions
# Uninstall old versions
$ sudo apt-get remove docker docker-engine docker.io
$ sudo apt-get remove docker docker-engine docker.io
Line 42: Line 45:
$ sudo apt-get update
$ sudo apt-get update
$ sudo apt-get install \
$ sudo apt-get install \
    apt-transport-https \
     ca-certificates \
     ca-certificates \
     curl \
     curl \
     software-properties-common
     gnupg \
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    lsb-release
# Note that for Linux Mint we need to change $(lsb_release -cs) to a proper name
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# For example, xenial for Mint 18.x and bionic for Mint 19.x
 
$ sudo add-apt-repository \
$ echo \
  "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  stable"
 
$ sudo apt-get update
$ sudo apt-get update
$ sudo apt-get install docker-ce
$ sudo apt-get install docker-ce docker-ce-cli containerd.io


# Verify
# Verify
$ sudo docker run hello-world  
$ sudo docker run hello-world  
</syntaxhighlight>
</pre>
Install docker-compose https://docs.docker.com/compose/install/
<pre>
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
</pre>
</li>
<li>[https://www.howtoforge.com/tutorial/how-to-install-kubernetes-on-ubuntu/ How to Install and Configure Kubernetes and Docker on Ubuntu 18.04 LTS] </li>
<li>[https://forums.linuxmint.com/viewtopic.php?t=414617 How install docker in Mint?]
</ul>
 
=== One-line script ===
https://github.com/docker/docker-install, https://docs.docker.com/engine/install/ubuntu/, https://twitter.com/portainerio/status/1650171336864550912


== Without sudo, Post-installation ==
Note that 1) the one-liner is a huge security issue. 2) but how will you add the current user to docker group and then logout and log back in. 3) Linux Mint does not work.
* https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/
<syntaxhighlight lang='sh'>
* [https://www.howtoforge.com/tutorial/docker-installation-and-usage-on-ubuntu-16.04/ Ubuntu 16.04]
$ curl -fsSL https://get.docker.com | bash
...
Client: Docker Engine - Community
Version:          24.0.7
API version:      1.43
Go version:       go1.20.10
Git commit:        afdd53b
Built:            Thu Oct 26 09:08:17 2023
OS/Arch:          linux/amd64
Context:          default


To use docker without ''sudo'', follow the instruction on [https://docs.docker.com/engine/installation/linux/linux-postinstall/#manage-docker-as-a-non-root-user the official guide].
Server: Docker Engine - Community
<pre>
Engine:
# Add the docker group if it doesn't already exist.
  Version:          24.0.7
# sudo groupadd docker
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.10
  Git commit:      311b9ff
  Built:            Thu Oct 26 09:08:17 2023
  OS/Arch:          linux/amd64
  Experimental:    false
containerd:
  Version:          1.6.26
  GitCommit:        3dd1e886e55dd695541fdcd67420c2888645a495
runc:
  Version:          1.1.10
  GitCommit:        v1.1.10-0-g18a0cb0
docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0


# Add your user to the docker group.
---------------
sudo usermod -aG docker $USER


# Log out and log in
To run Docker as a non-privileged user, consider setting up the
</pre>
Docker daemon in rootless mode for your user:


== CentOS ==
    dockerd-rootless-setuptool.sh install
https://docs.docker.com/engine/installation/linux/docker-ce/centos/


== Boot2Docker ==
Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.
For Windows and OS operation systems, we have to use Boot2Docker. Boot2Docker is a local virtual machine with its own network interface and IP address. To find the Boot2Docker IP address you can check the value of the DOCKER_HOST environment variable. You're be prompted to set this variable when you start or install Boot2Docker the first time. You can find the IP address by running ''boot2docker ip'' command.


Note that since Windows and OS X don't share a file system as Linux, the command 'docker run' with '-v' flag to mount a local directory into a Docker container will not work with Boot2Docker release prior to 1.3. The support for volumes is now available for OS X but is not yet present for Windows with the release of Boot2Docker 1.3.


== Windows ==
To run the Docker daemon as a fully privileged service, but granting non-root
Docker can be run on Windows 10 Pro as a native application; see
users access, refer to https://docs.docker.com/go/daemon-access/
* https://docs.docker.com/engine/installation/windows/.
 
* [https://tutorials.ubuntu.com/tutorial/tutorial-windows-ubuntu-hyperv-containers#0 Run Linux containers on Windows] & [https://linux.cn/article-8873-1.html?utm_source=rss&utm_medium=rss Chinese translation]
WARNING: Access to the remote API on a privileged Docker daemon is equivalent
        to root access on the host. Refer to the 'Docker daemon attack surface'
        documentation for details: https://docs.docker.com/go/attack-surface/


The information below is based on running Docker on Windows 7.1 and 8. Your processor needs to support hardware virtualization.
--------------
$ # sudo groupadd docker
$ sudo usermod -aG docker $USER; newgrp docker


* [https://github.com/boot2docker/windows-installer Windows Installer] includes msys-git, Virtualbox, Boot2Docker-cli management tool and Boot2Docker ISO.
$ docker run hello-world
* [https://docs.docker.com/installation/windows/#windows Installation instruction for Windows] OS. It will install Boot2Docker management tool with the boot2docker iso (based on [http://tinycorelinux.net/ Tiny Core Linux]), Virtualbox and MYSYS-git UNIX tools.
</syntaxhighlight>
* Docker needs Admin right to be installed. However, Virtualbox can be installed by user's account.
The '''newgrp docker''' command in Linux is used to switch the current user’s group ID during a login session. Specifically, it changes the user’s '''primary group''' to the docker group without logging out and back in. This is particularly useful when you need to gain the permissions associated with the docker group to run Docker commands.
* If the installer detects a version of VirtualBox installed, the VirtualBox checkbox will not be checked by default (Windows OS). The VirtualBox cannot be used anymore after updating my VB from 4.3.18 to 4.3.20. The error may be related to Windows update according to Virtualbox forum.
<pre>
<pre>
Error in supR3HardenedWinReSpawn
$ id -gn
docker
</pre>
</pre>
* Note that <span style="color: red">boot2docker cannot be installed/run inside a Windows guest machine</span>. See [https://github.com/boot2docker/windows-installer/issues/14 this post] and my Virtualbox wiki [[Virtualbox#Install_on_a_Windows_machine|here]]. If we try to launch boot2docker-vm from Virtualbox, we will see a message "This kernel requires an x86-64 CPU, but only detected an i686 CPU."
* After I switch back to an old version of virtualbox, every thing works again. I can even install Docker successfully.
** Boot2Docker Start icon cannot be run directly because Notepad++ will automatically open it. A possible solution is to go to control panel and change default program for .sh file from Notepad++ to C:\Program Files (x86)\Git\bin\bash.exe.
** The above step does not work well since a terminal appears and disappears quickly.
** A working approach is to open Git Bash from Start menu. And run /c/Program Files/Boot2DockerforWindows/start.sh (or ''boot2docker start'' or ''boot2docer init'')
** A new VM called 'boot2docker-vm' will be created (we can open VirtualBox Manager to check). But I got an error <span style="color: red">error in run: Failed to start machine "boot2docker-vm" (run again with -v for details)</span>. The VM has an error on Network>Adapter2>VirtualBox Host-Only Ethernet Adapter #2. So I open the setting of <boot2docker-vm>, go to Network > Adapter 2 and change the dropdown list of Name from  ''VirtualBox Host-Only Ethernet Adapter #2'' to ''VirtualBox Host-Only Ethernet Adapter''.
** Now it works either I directly click boot2docker-vm VM from VB Manager or use the command start.sh from Git Bash.


[[File:Boot2docker-vm.png|200px]]
=== Docker Desktop ===
* https://docs.docker.com/desktop/linux/install/
* [https://www.docker.com/blog/the-magic-of-docker-desktop-is-now-available-on-linux/ The Magic of Docker Desktop is Now Available on Linux]
* [https://ostechnix.com/docker-desktop-for-linux/ A Beginners Manual To Docker Desktop For Linux]
 
== Diet Pi ==
'''dietpi-software'''
<ul>
<li>Way 1: choose "Docker" but not "Docker Compose". Then I need to run the following too
<pre>
sudo apt install docker-compose-plugin
</pre>
<li>Way 2: Choose both "Docker Compose" and "Docker"
</ul>


== Manjaro Linux ==
[https://linuxconfig.org/manjaro-linux-docker-installation Manjaro Linux Docker installation]
<pre>
<pre>
$ # boot2docker is in the PATH variable, so there is not need to cd to the folder.
sudo pacman -Syu
$ boot2docker start
sudo pacman -S docker
initializing...
sudo systemctl start docker.service
Virtual machine boot2docker-vm already exists
sudo systemctl enable docker.service
sudo docker version
sudo usermod -aG docker $USER
sudo reboot


starting...
docker search r-base
Waiting for VM and Docker daemon to start...
</pre>
........o
Started.
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\ca.pem
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\cert.pem
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\key.pem
Docker client does not run on Windows for now. Please use
    "c:\Program files\Boot2Docker for Windows\boot2docker.exe" ssh
to SSH into the VM instead.


== Without sudo, Post-installation ==
* https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/
* [https://www.howtoforge.com/tutorial/docker-installation-and-usage-on-ubuntu-16.04/ Ubuntu 16.04]


192.168.56.101
To use docker without ''sudo'', follow the instruction on [https://docs.docker.com/engine/installation/linux/linux-postinstall/#manage-docker-as-a-non-root-user the official guide].
connecting...
<pre>
                        ##        .
# Add the docker group if it doesn't already exist.
                  ## ## ##      ==
# sudo groupadd docker
              ## ## ## ##      ===
          /""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
          \______ o          __/
            \    \        __/
              \____\______/
_                _  ____    _            _
| |__  ___  ___ | |_|___ \ __| | ___  ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|  < __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.4.1, build master : 86f7ec8 - Tue Dec 16 23:11:29 UTC 2014


Docker version 1.4.1, build 5bc2ff8
# Add your user to the docker group.
docker@boot2docker:~$ docker
sudo usermod -aG docker $USER
Usage: docker [OPTIONS] COMMAND [arg...]
 
# Log out and log in
</pre>
After running this command, you need to log out and log back in for the changes to take effect. This is because group membership is determined at login time. When you log in, the system reads the group membership information and assigns the appropriate permissions to your user account.


A self-sufficient runtime for linux containers.
== Upgrade Docker Desktop ==
It seems it does not affect running containers (e.g. RStudio on Mac).


Options:
== Is it fine to upgrade Docker-ce while a container is running? ==
  --api-enable-cors=false                      Enable CORS headers in the remote
[https://www.reddit.com/r/docker/comments/q21spb/comment/hfi97s4/ Doesn't matter. Your system will stop the container if you update docker.]
API
  -b, --bridge=""                              Attach containers to a pre-existi
ng network bridge
...
Run 'docker COMMAND --help' for more information on a command.
docker@boot2docker:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
hello-world:latest: The image you are pulling has been verified
511136ea3c5a: Pull complete
31cbccb51277: Pull complete
e45a5af57b00: Pull complete
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.


To generate this message, Docker took the following steps:
== Is there a way to hibernate a docker container ==
1. The Docker client contacted the Docker daemon.
* https://stackoverflow.com/a/45170070
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
* Reference for [https://docs.docker.com/engine/reference/commandline/checkpoint/ docker checkpoint] (This command is experimental)
    (Assuming it was not already locally available.)
3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.


To try something more ambitious, you can run an Ubuntu container with:
== Live restore ==
$ docker run -it ubuntu bash
* [https://stackoverflow.com/a/45352682 Can I save my running containers when upgrading from `docker` to `docker-ce`?]
* [https://www.sobyte.net/post/2022-05/docker-live-restore/ Docker's Live Restore feature] Docker provides a feature that keeps containers running when Daemon is unavailable, thus reducing container downtime when Daemon is upgraded or has problems. That feature is called '''Live Restore'''.


For more examples and ideas, visit:
== Rate limits for GitHub Apps ==
http://docs.docker.com/userguide/
[https://docs.github.com/en/developers/apps/rate-limits-for-github-apps Rate limits for GitHub Apps]
 
When I tried several times of ''docker build'', I finally got a message
{{Pre}}
Downloading GitHub repo XXX/XXXXX@HEAD
Error: Failed to install 'unknown package' from GitHub:
  HTTP error 403.
  API rate limit exceeded for XXX.XX.XXX.X. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
 
  Rate limit remaining: 0/60
  Rate limit reset at: 2021-04-12 20:32:28 UTC
 
  To increase your GitHub API rate limit
  - Use `usethis::browse_github_pat()` to create a Personal Access Token.
  - Use `usethis::edit_r_environ()` and add the token as `GITHUB_PAT`.
Execution halted
</pre>


docker@boot2docker:~$ ls
== CentOS ==
boot2docker, please format-me
<ul>
docker@boot2docker:~$ pwd
<li>https://docs.docker.com/engine/installation/linux/docker-ce/centos/. Note that Centos 9 Stream is required. I have tried to follow [https://linux.how2shout.com/how-to-install-docker-ce-on-oracle-linux-8-7/ this] to install on Oracle 7/8 and it does not work now. A possible workaround is either [https://docs.docker.com/engine/install/centos/ download RPM packages manually] ([https://download.docker.com/linux/centos/7/x86_64/stable/Packages/ CentOS 7], [https://download.docker.com/linux/centos/8/x86_64/stable/Packages/ CentOS 8]) or [https://docs.docker.com/engine/install/binaries/ Install Docker Engine from binaries].
/home/docker
{{Pre}}
docker@boot2docker:~$ ls /
sudo yum install -y yum-utils
bin/     dev/     home/   lib/     mnt/     proc/   run/     sys/     usr/
c/       etc/     init    linuxrc  opt/     root/   sbin/    tmp      var/


docker@boot2docker:~$ docker run hello-world
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Hello from Docker.
This message shows that your installation appears to be working correctly.


To generate this message, Docker took the following steps:
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.


To try something more ambitious, you can run an Ubuntu container with:
sudo systemctl start docker
$ docker run -it ubuntu bash
sudo systemctl enable docker.service
sudo systemctl enable containerd.service


For more examples and ideas, visit:
sudo docker run hello-world
http://docs.docker.com/userguide/
docker@boot2docker:~$
docker@boot2docker:~$
docker@boot2docker:~$
docker@boot2docker:~$ docker run -it ubuntu bash
Unable to find image 'ubuntu:latest' locally
ubuntu:latest: The image you are pulling has been verified
53f858aaaf03: Pull complete
837339b91538: Pull complete
615c102e2290: Pull complete
b39b81afc8ca: Pull complete
511136ea3c5a: Already exists
Status: Downloaded newer image for ubuntu:latest


sudo usermod -aG docker $USER
newgrp docker
</pre>


root@ea7e3289a01a:/# pwd
<li>[https://stackoverflow.com/questions/36545206/how-to-install-specific-version-of-docker-on-centos How to install specific version of Docker on Centos?]
/
<pre>
root@ea7e3289a01a:/# df -h
sudo yum list docker-ce.x86_64 --showduplicates | sort -r
Filesystem      Size  Used Avail Use% Mounted on
</pre>
rootfs          19G  269M  17G  2% /
</ul>
none            19G  269M  17G  2% /
tmpfs          1005M    0 1005M  0% /dev
shm              64M    0  64M  0% /dev/shm
/dev/sda1        19G  269M  17G  2% /etc/hosts
tmpfs          1005M    0 1005M  0% /proc/kcore
root@ea7e3289a01a:/# ls
bin  dev  home  lib64  mnt  proc  run  srv  tmp  var
boot  etc  lib  media  opt  root  sbin  sys  usr
root@ea7e3289a01a:/# exit
exit


== Boot2Docker ==
For Windows and OS operation systems, we have to use Boot2Docker. Boot2Docker is a local virtual machine with its own network interface and IP address. To find the Boot2Docker IP address you can check the value of the DOCKER_HOST environment variable. You're be prompted to set this variable when you start or install Boot2Docker the first time. You can find the IP address by running ''boot2docker ip'' command.


docker@boot2docker:~$ pwd
Note that since Windows and OS X don't share a file system as Linux, the command 'docker run' with '-v' flag to mount a local directory into a Docker container will not work with Boot2Docker release prior to 1.3. The support for volumes is now available for OS X but is not yet present for Windows with the release of Boot2Docker 1.3.
/home/docker
docker@boot2docker:~$ ls
boot2docker, please format-me
docker@boot2docker:~$ exit
[Press any key to exit]


brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
== Windows ==
$ boot2docker down
Note many of the information here have not been updated.


brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
Docker can be run on Windows 10 Pro as a native application; see
$
* https://docs.docker.com/engine/installation/windows/.
$ boot2docker --help
* [https://tutorials.ubuntu.com/tutorial/tutorial-windows-ubuntu-hyperv-containers#0 Run Linux containers on Windows] & [https://linux.cn/article-8873-1.html?utm_source=rss&utm_medium=rss Chinese translation]
Usage: c:\Program files\Boot2Docker for Windows\boot2docker.exe [<options>] <command> [<args>]


Boot2Docker management utility.
The information below is based on running Docker on Windows 7.1 and 8. Your processor needs to support hardware virtualization.


Commands:
* [https://github.com/boot2docker/windows-installer Windows Installer] includes msys-git, Virtualbox, Boot2Docker-cli management tool and Boot2Docker ISO.
  init                Create a new Boot2Docker VM.
* [https://docs.docker.com/installation/windows/#windows Installation instruction for Windows] OS. It will install Boot2Docker management tool with the boot2docker iso (based on [http://tinycorelinux.net/ Tiny Core Linux]), Virtualbox and MYSYS-git UNIX tools.
  up|start|boot      Start VM from any states.
* Docker needs Admin right to be installed. However, Virtualbox can be installed by user's account.
  ssh [ssh-command]   Login to VM via SSH.
* If the installer detects a version of VirtualBox installed, the VirtualBox checkbox will not be checked by default (Windows OS). The VirtualBox cannot be used anymore after updating my VB from 4.3.18 to 4.3.20. The error may be related to Windows update according to Virtualbox forum.
  save|suspend        Suspend VM and save state to disk.
<pre>
  down|stop|halt      Gracefully shutdown the VM.
Error in supR3HardenedWinReSpawn
  restart            Gracefully reboot the VM.
</pre>
  poweroff            Forcefully power off the VM (may corrupt disk image).
* Note that <span style="color: red">boot2docker cannot be installed/run inside a Windows guest machine</span>. See [https://github.com/boot2docker/windows-installer/issues/14 this post] and my Virtualbox wiki [[Virtualbox#Install_on_a_Windows_machine|here]]. If we try to launch boot2docker-vm from Virtualbox, we will see a message "This kernel requires an x86-64 CPU, but only detected an i686 CPU."
  reset              Forcefully power cycle the VM (may corrupt disk image).
* After I switch back to an old version of virtualbox, every thing works again. I can even install Docker successfully.  
  delete|destroy      Delete Boot2Docker VM and its disk image.
** Boot2Docker Start icon cannot be run directly because Notepad++ will automatically open it. A possible solution is to go to control panel and change default program for .sh file from Notepad++ to C:\Program Files (x86)\Git\bin\bash.exe.
  config|cfg          Show selected profile file settings.
** The above step does not work well since a terminal appears and disappears quickly.
  info                Display detailed information of VM.
** A working approach is to open Git Bash from Start menu. And run /c/Program Files/Boot2DockerforWindows/start.sh (or ''boot2docker start'' or ''boot2docer init'')
  ip                  Display the IP address of the VM's Host-only network.
** A new VM called 'boot2docker-vm' will be created (we can open VirtualBox Manager to check). But I got an error <span style="color: red">error in run: Failed to start machine "boot2docker-vm" (run again with -v for details)</span>. The VM has an error on Network>Adapter2>VirtualBox Host-Only Ethernet Adapter #2. So I open the setting of <boot2docker-vm>, go to Network > Adapter 2 and change the dropdown list of Name from  ''VirtualBox Host-Only Ethernet Adapter #2'' to ''VirtualBox Host-Only Ethernet Adapter''.
  shellinit          Display the shell commands to set up the Docker client.
** Now it works either I directly click boot2docker-vm VM from VB Manager or use the command start.sh from Git Bash.
  status              Display current state of VM.
  download            Download Boot2Docker ISO image.
  upgrade            Upgrade the Boot2Docker ISO image (restart if running).
  version            Display version information.


Options:
[[File:Boot2docker-vm.png|200px]]
      --basevmdk="": Path to VMDK to use as base for persistent partition
      --clobber=false: overwrite Docker client binary on boot2docker upgrade
      --dhcp=true: enable VirtualBox host-only network DHCP.
      --dhcpip=192.168.59.99: VirtualBox host-only network DHCP server address.
....
  -v, --verbose=false: display verbose command invocations.
      --vm="boot2docker-vm": virtual machine name.
      --waittime=300: Time in milliseconds to wait between port knocking retries during 'start'
error in run: config error: pflag: help requested


brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
<pre>
</pre>
$ # boot2docker is in the PATH variable, so there is not need to cd to the folder.
$ boot2docker start
initializing...
Virtual machine boot2docker-vm already exists
 
starting...
Waiting for VM and Docker daemon to start...
........o
Started.
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\ca.pem
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\cert.pem
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\key.pem
Docker client does not run on Windows for now. Please use
    "c:\Program files\Boot2Docker for Windows\boot2docker.exe" ssh
to SSH into the VM instead.


The big picture
<pre>


                          start.sh                      docker run -it ubuntu bash
192.168.56.101
Git Bash Git Bash        ----------> boot2docker-vm      ------------->  ubuntu
connecting...
                                  docker@boot2docker:
                        ##        .
   <-------               <----------                      <-------------
                  ## ## ##      ==
  boot2docker down          exit                                exit
              ## ## ## ##      ===
  (shutdown boot2docker) (boot2docker-vm is still on)
          /""""""""""""""""\___/ ===
    |
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
    |
          \______ o          __/
    | boot2docker up (start boot2docker)
            \   \        __/
    |
               \____\______/
    boot2docker ssh (log into docker acct)
_                _  ____    _            _
    |
| |__  ___  ___ | |_|___ \ __| | ___  ___| | _____ _ __
    v
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
  boot2docker-vm
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   < __/ |
  docker@boot2docker
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
</pre>
Boot2Docker version 1.4.1, build master : 86f7ec8 - Tue Dec 16 23:11:29 UTC 2014


=== Increase boot2docker vmdk space ===
Docker version 1.4.1, build 5bc2ff8
https://docs.docker.com/articles/b2d_volume_resize/
docker@boot2docker:~$ docker
Usage: docker [OPTIONS] COMMAND [arg...]


=== Install utilities in Boot2docker VM ===
A self-sufficient runtime for linux containers.
http://blog.tutum.co/2014/11/05/how-to-use-docker-on-windows/


For example, to install cifs-utils,
Options:
<pre>
  --api-enable-cors=false                      Enable CORS headers in the remote
wget http://distro.ibiblio.org/tinycorelinux/5.x/x86/tcz/cifs-utils.tcz
API
tce-load -i cifs-utils.tcz
  -b, --bridge=""                              Attach containers to a pre-existi
</pre>
ng network bridge
...
Run 'docker COMMAND --help' for more information on a command.
docker@boot2docker:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
hello-world:latest: The image you are pulling has been verified
511136ea3c5a: Pull complete
31cbccb51277: Pull complete
e45a5af57b00: Pull complete
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.
 
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.


== Mac ==
To try something more ambitious, you can run an Ubuntu container with:
If you have Mac, you don't have to use boot2docker (iso & its management tool). You can use other Linux which comes with docker pre-installed. See [https://serversforhackers.com/getting-started-with-docker/ this post].
$ docker run -it ubuntu bash


== ARM architeture from hub.docker.com ==
For more examples and ideas, visit:
* Raspberry Pi
http://docs.docker.com/userguide/
** [https://www.raspberrypi.org/blog/docker-comes-to-raspberry-pi/ Docker Swarm on Raspberry Pi]
** [https://linuxhint.com/install_docker_on_raspbian_os/ How to Install Docker on Raspbian OS] by Shahriar Shovon.
** [https://blog.hypriot.com/getting-started-with-docker-on-your-arm-device/ Getting started with Docker on your Raspberry Pi]
::<syntaxhighlight lang='bash'>
curl -sSL https://get.docker.com | sh
</syntaxhighlight>
* See Odroid magazine 2015 January and 2015 February. Note that the current versions of Docker and Docker Hub are not aware of the architecture for which the image has been built. All standard images are intended for the x86 architecture, and the autobuild feature offered by the Docker registry is only available for x86.
* [https://blog.hypriot.com/post/nvidia-jetson-nano-intro/ NVIDIA Jetson Nano Developer Kit - Introduction], [http://collabnix.com/running-redis-inside-docker-container-on-jetson-nano/ Redis running inside Docker container on NVIDIA Jetson Nano]
:<syntaxhighlight lang='bash'>
sudo apt install curl
curl -sSL https://get.docker.com/ | sh
</syntaxhighlight>
* [https://matchboxdorry.gitbooks.io/matchboxblog/content/blogs/build_and_run_arm_images.html How to Build and Run ARM Docker Images on x86 Hosts]


== GUI/TUI interface manager ==
docker@boot2docker:~$ ls
=== [https://github.com/moncho/dry Dry] ===
boot2docker, please format-me
[https://www.2daygeek.com/dry-an-interactive-cli-manager-for-docker-containers/ Dry – An Interactive CLI Manager For Docker Containers]. The TUI is built on top of [https://github.com/gizak/termui termui]; a cross-platform, easy-to-compile, and fully-customizable terminal dashboard. It is inspired by [https://github.com/yaronn/blessed-contrib blessed-contrib], but purely in Go.
docker@boot2docker:~$ pwd
/home/docker
docker@boot2docker:~$ ls /
bin/     dev/     home/   lib/     mnt/     proc/   run/     sys/     usr/
c/       etc/     init    linuxrc  opt/     root/   sbin/   tmp      var/


=== LazyDocker (TUI) ===
docker@boot2docker:~$ docker run hello-world
[https://www.linuxuprising.com/2019/07/lazydocker-new-docker-and-docker.html?m=1 LazyDocker: New Docker And Docker Compose Terminal UI], [https://github.com/jesseduffield/lazydocker Github]
Hello from Docker.
This message shows that your installation appears to be working correctly.


=== Dockly (TUI) ===
To generate this message, Docker took the following steps:
[https://www.ostechnix.com/dockly-manage-docker-containers-from-terminal/ Dockly – Manage Docker Containers From Terminal]
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.


=== [https://portainer.io/ Portainer]* (nice) ===
To try something more ambitious, you can run an Ubuntu container with:
* https://portainer.readthedocs.io/en/stable/deployment.html#manage-a-new-docker-environment <syntaxhighlight lang='bash'>
$ docker run -it ubuntu bash
docker run -d -p 9000:9000 \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v portainer_data:/data portainer/portainer \
    -H tcp://192.168.1.98:2375
</syntaxhighlight>
: Go to http://192.168.1.98:9000. But I still don't see the other containers that are running now:(


* [https://dzone.com/articles/a-comparison-of-docker-guis A Comparison of Docker GUIs] <syntaxhighlight lang='bash'>
For more examples and ideas, visit:
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
http://docs.docker.com/userguide/
</syntaxhighlight>
docker@boot2docker:~$
: A username/password is required to access the page unless we use the '''--no-auth''' option; see [https://portainer.readthedocs.io/en/stable/configuration.html Configuration].
docker@boot2docker:~$
* [https://www.howtoforge.com/tutorial/ubuntu-docker-portainer/ How to Manage Docker Containers using Portainer on Ubuntu 16.04]. Go to Local. It will show the status of all local stacks, containers, volumes and images. Very Cool!
docker@boot2docker:~$
 
docker@boot2docker:~$ docker run -it ubuntu bash
=== [https://github.com/crosbymichael/dockerui DockerUI] (Deprecated, Development continues at Portainer)===
Unable to find image 'ubuntu:latest' locally
https://github.com/kevana/ui-for-docker. A quick start:
ubuntu:latest: The image you are pulling has been verified
# Run: <syntaxhighlight lang='bash'>
53f858aaaf03: Pull complete
docker run -d -p 9000:9000 --privileged \
837339b91538: Pull complete
    -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
615c102e2290: Pull complete
</syntaxhighlight>  where '''-v''' means to bind mount a volume.
b39b81afc8ca: Pull complete
# Open your browser to http://<dockerd host ip>:9000
511136ea3c5a: Already exists
Status: Downloaded newer image for ubuntu:latest


Note: Anyone in the local network can access the website without any authentication.


=== Rancher ===
root@ea7e3289a01a:/# pwd
* https://rancher.com/quick-start/. The doc above is not good enough to follow. Search Google for tutorial or get started guide including screenshots.
/
* [https://www.howtoforge.com/tutorial/ubuntu-rancher-docker-container-manager/ How to Manage Docker Containers with Rancher on Ubuntu 16.04]
root@ea7e3289a01a:/# df -h
* [https://hackernoon.com/creating-a-scalable-application-using-docker-rancher-rancheros-cattle-5feb83a3e743 Creating A Scalable Application Using Docker + Rancher + RancherOs + Cattle]
Filesystem      Size  Used Avail Use% Mounted on
* Initial setup video https://youtu.be/1EMW1y7529Y
rootfs          19G  269M  17G  2% /
* Training from Rancher Labs https://youtu.be/8K14A_CZFdI. It seems Rancher is complicated but powerful. The whole operation is like Amazon Cloud.
none            19G  269M  17G  2% /
* [https://gist.github.com/lmmendes/fbed32a452cf02d2a1095658795cb3d2 Running Rancher locally (with two hosts) using MacOS Docker and VirtualBox]
tmpfs          1005M    0 1005M  0% /dev
* To allow UDP port
shm              64M    0  64M  0% /dev/shm
<syntaxhighlight lang='bash'>
/dev/sda1        19G  269M  17G  2% /etc/hosts
$ sudo apt-get install ufw
tmpfs          1005M    0 1005M  0% /proc/kcore
$ sudo ufw allow 4500/udp
root@ea7e3289a01a:/# ls
$ sudo ufw allow 500/udp
bin  dev  home  lib64  mnt  proc  run  srv  tmp  var
</syntaxhighlight>
boot  etc  lib  media  opt  root  sbin  sys  usr
* discoposse.com
root@ea7e3289a01a:/# exit
** [http://discoposse.com/2015/11/08/rancher-part-1-installing-rancher-and-setting-access-control/ Part 1] Installing Rancher and Setting Access Control
exit
** [http://discoposse.com/2015/11/09/rancher-part-2-adding-a-docker-host-to-rancher/ Part 2] Adding a Docker Host to Rancher
** [http://discoposse.com/2015/11/12/rancher-part-3-adding-the-dockerhub-to-our-rancher-registry/ Part 3] Adding the DockerHub to our Rancher Registry
** [http://discoposse.com/2015/11/13/rancher-part-4-using-the-catalog-example-with-glusterfs/ Part 4] Using the Catalog Example with GlusterFS


=== [https://github.com/tobegit3hub/seagull Seagull] ===
https://youtu.be/TuT5gb8oRw8


<pre>
docker@boot2docker:~$ pwd
docker run -d -p 127.0.0.1:10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull
/home/docker
</pre>
docker@boot2docker:~$ ls
boot2docker, please format-me
docker@boot2docker:~$ exit
[Press any key to exit]


The only issue is there is no username/password to protect other people to access the web GUI. The solution of binding to localhost to restrict the access does not work for remote administration.
brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
$ boot2docker down


That is, the tool is suitable for home use.
brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
$
$ boot2docker --help
Usage: c:\Program files\Boot2Docker for Windows\boot2docker.exe [<options>] <command> [<args>]


=== [https://kitematic.com/ Kitematic] (Mac and Windows only) ===
Boot2Docker management utility.
Available for Mac OS X 10.8+ and Windows 7+ (64-bit) and Ubuntu. https://github.com/docker/kitematic/releases/


Run containers through a simple, yet powerful graphical user interface.
Commands:
 
  init                Create a new Boot2Docker VM.
A [https://www.r-bloggers.com/share-your-shiny-apps-with-docker-and-kitematic/ Share your Shiny Apps with Docker and Kitematic!]
  up|start|boot      Start VM from any states.
 
  ssh [ssh-command]  Login to VM via SSH.
=== [https://github.com/shipyard/shipyard Shipyard] (retired) ===
  save|suspend        Suspend VM and save state to disk.
* [https://www.sumologic.com/blog/code/managing-containers-docker-shipyard/ Managing Containers with Docker Shipyard]
  down|stop|halt      Gracefully shutdown the VM.
* Three alternatives:
  restart            Gracefully reboot the VM.
** [http://rancher.com/ Rancher]
  poweroff            Forcefully power off the VM (may corrupt disk image).
** [https://github.com/kevana/ui-for-docker Docker UI]
  reset              Forcefully power cycle the VM (may corrupt disk image).
** [https://portainer.io/ Portainer]
  delete|destroy      Delete Boot2Docker VM and its disk image.
  config|cfg          Show selected profile file settings.
  info                Display detailed information of VM.
  ip                  Display the IP address of the VM's Host-only network.
  shellinit          Display the shell commands to set up the Docker client.
  status              Display current state of VM.
  download            Download Boot2Docker ISO image.
  upgrade            Upgrade the Boot2Docker ISO image (restart if running).
  version            Display version information.


= Usage =
Options:
== Basics, docs, cheatsheet ==
      --basevmdk="": Path to VMDK to use as base for persistent partition
* https://docs.docker.com/articles/basics/
      --clobber=false: overwrite Docker client binary on boot2docker upgrade
* https://www.docker.com/sites/default/files/d8/2019-09/docker-cheat-sheet.pdf
      --dhcp=true: enable VirtualBox host-only network DHCP.
* https://coderwall.com/p/2es5jw/docker-cheat-sheet-with-examples
      --dhcpip=192.168.59.99: VirtualBox host-only network DHCP server address.
* https://github.com/wsargent/docker-cheat-sheet
....
* [https://www.howtoforge.com/tutorial/how-to-use-docker-introduction/ How to use Docker in a practical way]
  -v, --verbose=false: display verbose command invocations.
* https://hackernoon.com/introduction-to-docker-a7d9e1f6c0b3#.tezit0hkq
      --vm="boot2docker-vm": virtual machine name.
* [http://www.cnblogs.com/wanliwang01/p/docker01.html Docker快速入门]
      --waittime=300: Time in milliseconds to wait between port knocking retries during 'start'
* [http://blog.myplanet.com/docker-the-fun-and-easy-way Docker: The Fun and Easy Way]
error in run: config error: pflag: help requested


Note that we need '''sudo''' is needed unless it is on a Mac OS.
brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
</pre>


If docker cannot find an image, it will try to pull it from its repository.
The big picture
<pre>
<pre>
$ sudo docker run -it ubuntu /bin/bash
 
Unable to find image 'ubuntu' locally
                          start.sh                      docker run -it ubuntu bash
Pulling repository ubuntu
Git Bash Git Bash        ---------->  boot2docker-vm      ------------->  ubuntu
04c5d3b7b065: Download complete
                                  docker@boot2docker:
511136ea3c5a: Download complete
  <-------              <----------                      <-------------
c7b7c6419568: Download complete
  boot2docker down          exit                                exit
70c8faa62a44: Download complete
  (shutdown boot2docker) (boot2docker-vm is still on)
d735006ad9c1: Download complete
    |
root@ec83b3ac878d:/#
    |
    |  boot2docker up (start boot2docker)
    |
    |  boot2docker ssh (log into docker acct)
    |
    v
  boot2docker-vm
  docker@boot2docker
</pre>
</pre>


{| class="wikitable"
=== Increase boot2docker vmdk space ===
! purpose
https://docs.docker.com/articles/b2d_volume_resize/
! command
 
|-
=== Install utilities in Boot2docker VM ===
| run a container
http://blog.tutum.co/2014/11/05/how-to-use-docker-on-windows/
| docker container run -d -p 80:80 httpd
|-
| list running cotainer
| docker container ls
|-
| view logs of Docker container
| docker container logs cranky_cori
|-
| identify Docker container process?
| docker container top  cranky_cori
|-
| stop Docker container?
| docker container stop cranky_cori
|-
| list stopped or not running Docker containers
| docker container ls -a
|-
| start Docker container
| docker container start c46f2e9e4690
|-
| remove Docker container
| docker container rm cranky_cori
|-
| list Docker images
| docker images
|-
| remove Docker image
| docker rmi iman/touch
|}


=== Restart docker daemon ===
For example, to install cifs-utils,
When I try the Chap5 > Continuous integration (Jenkins) of the Docker Book, I found I cannot stop/kill the container. See others' report [https://github.com/docker/docker/issues/1906 here]. The solution is to restart the docker daemon.
<pre>
<pre>
sudo service docker start
wget http://distro.ibiblio.org/tinycorelinux/5.x/x86/tcz/cifs-utils.tcz
tce-load -i cifs-utils.tcz
</pre>
</pre>
After that, I can stop and rm the container.
 
=== WSL2 ===
* [https://poweruser.blog/docker-on-windows-10-without-hyper-v-a529897ed1cc Docker on Windows without Hyper-V]
* [https://docs.microsoft.com/en-us/windows/wsl/install-manual Manual installation steps for older versions of WSL]. I got this page when I installed Docker Desktop v4.9.0 (2022/6/14) on Windows 10.
 
== Mac ==
<ul>
<li>https://docs.docker.com/desktop/mac/
<li>Alternatives to Docker Desktop for Mac? Rancher is recommended. 2022-06-08
<li>Vagrant method. If you have Mac, you don't have to use boot2docker (iso & its management tool). You can use other Linux which comes with docker pre-installed. See [https://serversforhackers.com/getting-started-with-docker/ this post].
<li>To avoid the message ''Error: `brew cask` is no longer a `brew` command. Use `brew <command> --cask` instead'', use
<pre>
<pre>
sudo docker stop jenkins
brew install --cask docker
sudo docker rm jenkins
sudo docker ps -a
</pre>
</pre>
</ul>


=== images vs containers ===
== Raspberry Pi ==
<pre>
* [https://docs.balena.io/reference/hardware/devices/ Resin.io] (now called [https://www.balena.io/ balenaCloud]). They are supporting Docker on very low performance devices like Raspberry Pi 1 Zero or Beaglebone Black (512MB RAM, 1GHz ARM® Cortex-A8).
$ sudo docker images
* Another option is to use QEMU which allows Docker to create a container based on ARM. [https://ricardodeazambuja.com/rpi/2020/12/29/rpi2docker/ Creating a docker container from a Raspberry Pi Zero image... and the other way around]
REPOSITORY                    TAG                IMAGE ID            CREATED              VIRTUAL SIZE
* [https://phoenixnap.com/kb/docker-on-raspberry-pi Docker on Raspberry Pi - Installation/uninstall Guide]
iman                          latest              6e0f5644b2fd        About a minute ago  460.4 MB
* [https://raspberrytips.com/docker-on-raspberry-pi/ Getting Started With Docker On Raspberry Pi (Full Guide)]
iman/touch                    latest              77b9ac5951c2        4 minutes ago        460.4 MB
<none>                        <none>              aaa75e64ddf0        5 weeks ago          188.3 MB
ouruser/sinatra                v2                  ea8c9f407a8d        5 weeks ago          447 MB
ubuntu                        14.04              ed5a78b7b42b        5 weeks ago          188.3 MB
ubuntu                        latest              ed5a78b7b42b        5 weeks ago          188.3 MB
eddelbuettel/docker-ubuntu-r  add-r-devel-san    3c19d078c5d9        3 months ago        460.4 MB
hello-world                    latest              ef872312fe1b        4 months ago        910 B
training/sinatra              latest              f0f4ab557f95        8 months ago        447 MB


$ sudo docker ps -a
== ARM architeture from hub.docker.com ==
CONTAINER ID IMAGE                                          COMMAND              CREATED        STATUS                  PORTS NAMES
* [https://www.docker.com/blog/getting-started-with-docker-for-arm-on-linux/ Getting started with Docker for Arm on Linux]
8fbdbcdb5126 iman/touch:latest                              "/bin/bash"          2 minutes ago  Exited (0) 2 minutes ago      thirsty_engelbart 
* Raspberry Pi
dc9e82f2c00a eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          9 minutes ago  Exited (0) 3 minutes ago      kickass_bardeen   
** [https://www.raspberrypi.org/blog/docker-comes-to-raspberry-pi/ Docker Swarm on Raspberry Pi]
532a90f36aa8 eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        happy_lalande     
** [https://linuxhint.com/install_docker_on_raspbian_os/ How to Install Docker on Raspbian OS] by Shahriar Shovon.
7634024ee0bf eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        insane_mclean     
** [https://blog.hypriot.com/getting-started-with-docker-on-your-arm-device/ Getting started with Docker on your Raspberry Pi]
14034a9720cb eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        naughty_lumiere   
::<syntaxhighlight lang='bash'>
ca90954628db eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          19 hours ago  Exited (130) 18 hours ago      sick_hawking       
curl -sSL https://get.docker.com | sh
8bbdcb7c339f eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          19 hours ago  Exited (0) 19 hours ago        modest_davinci     
</syntaxhighlight>
e8e24f80f0dd aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      berserk_hodgkin   
* UDOO Quad running Armbian 20.04
d41959e0eb55 aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      jovial_curie       
** The instruction on official Docker website does not work
b408c0e2805b aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      lonely_tesla       
** The curl command method above does not work
72a551e4b492 ouruser/sinatra:v2                            "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        jolly_meitner     
** '''sudo apt-get install -y docker.io''' works (''docker -v'' shows it is 19.03.8). After that, run '''sudo usermod -aG docker $USER''' and log out/in.
75fd6cc4658b training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        evil_yalow         
* See Odroid magazine 2015 January and 2015 February. Note that the current versions of Docker and Docker Hub are not aware of the architecture for which the image has been built. All standard images are intended for the x86 architecture, and the autobuild feature offered by the Docker registry is only available for x86.
cc8886f5a02e training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (130) 5 weeks ago      elegant_curie     
* [https://blog.hypriot.com/post/nvidia-jetson-nano-intro/ NVIDIA Jetson Nano Developer Kit - Introduction], [http://collabnix.com/running-redis-inside-docker-container-on-jetson-nano/ Redis running inside Docker container on NVIDIA Jetson Nano]
0585e4f5fecd eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        elated_euclid     
:<syntaxhighlight lang='bash'>
brb@brbweb4:~/Downloads$
sudo apt install curl
</pre>
curl -sSL https://get.docker.com/ | sh
</syntaxhighlight>
* [https://matchboxdorry.gitbooks.io/matchboxblog/content/blogs/build_and_run_arm_images.html How to Build and Run ARM Docker Images on x86 Hosts]


When we want to delete a container, we use the container's '''CONTAINER ID''' or '''NAME''' (last column output from docker ps -a). But when we want to delete an image, we use the image's '''REPOSITORY''' or '''IMAGE ID''' (2nd column output from docker images)
=== docker-compose ===
<ul>
<li>https://docs.docker.com/compose/install/. The binary version is only available for x86. So for raspi, see the Alternative Install Options where it suggests to use [https://docs.python-guide.org/dev/virtualenvs/ virtualenv]. See also [[Python#virtualenv|Python &rarr; virtualenv]].</li>
<li>[https://withblue.ink/2020/06/24/docker-and-docker-compose-on-raspberry-pi-os.html Docker and Docker Compose on Raspberry Pi OS]
<pre>
<pre>
$ sudo docker rm thirsty_engelbart  # iman/touch
sudo apt update
$ sudo docker rm dc9e82f2c00a      # eddelbuettel/docker-ubuntu-r:add-r-devel-san
sudo apt install -y python3-pip libffi-dev
$ sudo docker ps -a  # check to see the container is gone now
# Install Docker Compose from pip (using Python3)
# This might take a while
sudo pip3 install docker-compose
</pre>
</li>
</ul>


$ sudo docker rmi 6e0f5644b2fd
=== Some examples* ===
$ sudo docker rmi iman/touch
Not I use the arm64 image on my Pi3b+.
$ sudo docker images  # check to see the images are gone now
 
[https://fleet.linuxserver.io/ Images] from https://www.linuxserver.io/. Some indices include number of pulls and stars.
 
[https://en.wikipedia.org/wiki/List_of_tz_database_time_zones List of tz database time zones]
 
'''[https://documentation.portainer.io/v2.0/deploy/linux/ Portainer]'''. The port number is 9000. Note '''the stack will be deployed using the equivalent of docker-compose. Only Compose file format version 2 is supported at the moment.'''
 
'''[https://hub.docker.com/r/trnape/rpi-samba Samba]'''. Tested on iOS, Ubuntu & Windows 10.
<pre>
mkdir -p /mnt/usb/share/{data,backups}
mkdir /mnt/usb/share/data/{alice,bob,documents}
touch /mnt/usb/share/backups/backupsfile
touch /mnt/usb/share/data/bob/bobfile
touch /mnt/usb/share/data/documents/documentfile
 
docker run -d -p 445:445 \
  -v /mnt/usb/share/data:/share/data \
  -v /mnt/usb/share/backups:/share/backups \
  --name rpi-samba trnape/rpi-samba \
  -u "alice:abc123" \
  -u "bob:secret" \
  -u "guest:guest" \
  -s "Backup directory:/share/backups:rw:alice,bob" \
  -s "Bob (private):/share/data/bob:rw:bob" \
  -s "Documents (readonly):/share/data/documents:ro:guest,alice,bob"
</pre>
</pre>
On '''Windows''', 1) right click on 'This PC' and choose 'Add a network location'. 2) type \\192.168.1.249\ and the dropdown list will populate all available folders. 3) choose the one (e.g. Bob) and then enter the credential. Done. On '''Ubuntu''', just type smb://192.168.1.249/. It will then populate the available folders.
'''[https://www.digitalocean.com/community/tutorials/how-to-run-nginx-in-a-docker-container-on-ubuntu-14-04 Nginx]'''
<pre>
mkdir -p /mnt/usb/docker-nginx/html
echo "hello world" >> /mnt/usb/docker-nginx/html/index.html
nano /mnt/usb/docker-nginx/html/sharefile
docker run --name rpi-nginx -p 8086:80 \
  --restart always \
  -v /mnt/usb/docker-nginx/html:/usr/share/nginx/html \
  -d nginx:stable-alpine


=== Command line interface, CLI ===
# Or a stack file
https://docs.docker.com/engine/reference/commandline/cli/ Docker command line
version: '2'
services:
    nginx:
        container_name: rpi-nginx
        ports:
            - '8086:80'
        restart: always
        volumes:
            - '/mnt/usb/docker-nginx/html:/usr/share/nginx/html'
        image: nginx:stable-alpine
</pre>
Note consider to use a samba share folder (see above) as a nginx document root.
<pre>
<pre>
$ docker
cp /mnt/usb/docker-nginx/html/* /mnt/usb/share/data/bob/
rm -rf /mnt/usb/docker-nginx/html
ln -s /mnt/usb/share/data/bob/ /mnt/usb/docker-nginx/html
</pre>
 
'''[https://github.com/michaelmiklis/docker-rpi-monitor Rpi-monitor]'''. I need to change '''/dev/vcsm''' to '''/dev/vcsm-cma'''. But the temperature part is not working. I am using 64-bit Raspberry Pi OS and it does not show attached USB disks. The port number is 8888.


Usage: docker COMMAND
'''[https://registry.hub.docker.com/r/linuxserver/code-server/ code-server]'''
<pre>
---
version: "2.1"
services:
  code-server:
    image: ghcr.io/linuxserver/code-server
    container_name: code-server
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
      - PASSWORD=password #optional
      - SUDO_PASSWORD=password #optional
    volumes:
      - /mnt/usb/code-server:/config
    ports:
      - 8443:8443
    restart: unless-stopped
</pre>


A self-sufficient runtime for containers
'''[https://docs.linuxserver.io/images/docker-mstream mstream]''' Music streaming. Works great.


Options:
'''[https://registry.hub.docker.com/r/emby/embyserver/#installation emby]''' does not work on arm64. It works on x86 though. Even I copy a mp4 file to movies directory the movie does not show up:(
      --config string      Location of client config files (default "/home/brb/.docker")
<pre>
  -D, --debug              Enable debug mode
version: '2.1'
  -H, --host list          Daemon socket(s) to connect to
services:
  -l, --log-level string  Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
    embyserver:
      --tls                Use TLS; implied by --tlsverify
        container_name: emby
      --tlscacert string   Trust certs signed only by this CA (default "/home/brb/.docker/ca.pem")
        network_mode: bridge
      --tlscert string    Path to TLS certificate file (default "/home/brb/.docker/cert.pem")
        restart: always
      --tlskey string      Path to TLS key file (default "/home/brb/.docker/key.pem")
        environment:
      --tlsverify          Use TLS and verify the remote
            - VERSION=latest
   -v, --version            Print version information and quit
            - UID=1000
            - GID=1000
            - TZ=America/Denver
        volumes:
            - /media/crucial/emby/config:/config
            - /media/crucial/emby/tv:/mnt/tv
            - /media/crucial/emby/movies:/mnt/movies
        ports:
            - 8096:8096           
        image: 'emby/embyserver:latest'
</pre>
 
'''[https://github.com/linuxserver/docker-jellyfin jellyfin]''' Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. [https://youtu.be/c28kUNKJcqQ How to Install Jellyfin on Docker with Portainer]
 
'''[https://github.com/greensheep/plex-server-docker-rpi plex]''' We can access the plex server via http://IP:32400/web. Note that in the first server setup, we need to add '''Library'''' by choosing the new library name (eg Other Videos) shown on plex & the data source (eg /data) so our own media can be found. After we added new media files we can rescan by clicking the vertical 3 dots icon and selecting scan library files. Pi3b+ is still a little weak since I can see all threads are busy when I played a mp4 file.
{{Pre}}
mkdir -p /mnt/usb/plex/{config,data}
cp FILENAme.mp4 /mnt/usb/plex/data
docker run \
  -d \
  --name plex \
  --net host \
  -p 32400:32400 \
   --restart always \
  --volume /mnt/usb/plex/config:/config \
  --volume /mnt/usb/plex/data:/data \
   greensheep/plex-server-docker-rpi:latest


Management Commands:
WARNING: The requested image's platform (linux/arm) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
  config      Manage Docker configs
</pre>
  container  Manage containers
  image       Manage images
  network    Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service    Manage services
  swarm      Manage Swarm
  system      Manage Docker
  trust      Manage trust on Docker images
  volume      Manage volumes


Commands:
'''[https://youtu.be/7EoEll0lVXc Nextcloud]'''.
  attach      Attach local standard input, output, and error streams to a running container
<pre>
  build      Build an image from a Dockerfile
sudo mkdir -p /srv/dev-disk-by-label-Files/Databases/NextCloud
  commit      Create a new image from a container's changes
sudo mkdir -p /srv/dev-disk-by-label-Files/Config/Nextcloud
  cp          Copy files/folders between a container and the local filesystem
</pre>
  create     Create a new container
After that, copy and paste the [https://gist.github.com/dnburgess/fdcaf27280e031fe88dd2fb9728649f6 stack] into portainer. Wait for a few minutes on RPi3. The port number is 8080. Now we can create the admin username/password such as nextcloud/nextcloud. Click the little triangle next to "Storage and Database". Change to MySQL. In the next part we enter nextcloud/nextcloud/nextcloud/db (note the "db" replaces localhost b/c we use "db" as the service name). Again, wait for a few minutes.
  diff        Inspect changes to files or directories on a container's filesystem
 
  events      Get real time events from the server
'''[https://youtu.be/I3fOq6zx1Zk?t=305 Heimdall]''' (Dashboard for web apps). I keep the PUID (1000) and PGID (1000). The instruction says it is from the '''admin''' user account but I don't find ''admin'' account? Change the volume to /srv/dev-disk-by-label-Files/Config/Heimdall (use '''sudo mkdir''' to create the directory on terminal). Change the port to 83 & remove port 443. Define the endpoint from Portainer -> Endpoints -> local -> Public IP as ''raspberrypi.local'' (depending on your hostname). We need to wait a little bit. Now go to the container and find heimdall and click the port in order to open the website correctly (instead 0.0.0.0). I can add apps like nextcloud, portainer, pi-hole, other servers, etc. The '''Application Type''' entry has a good list of popular apps and it will pre-populate the button icon and the background color for our app.
  exec        Run a command in a running container
 
  export      Export a container's filesystem as a tar archive
'''[https://hub.docker.com/r/linuxserver/taisun taisun]''' The default port is 3000
  history    Show the history of an image
 
  images      List images
'''[https://yacht.sh/Installation/yacht/ yacht]'''. The default login is '''[email protected]''' and '''pass'''. The name shown on portainer is '''pedantic_hermann'''
  import      Import the contents from a tarball to create a filesystem image
{{Pre}}
  info        Display system-wide information
docker volume create yacht
  inspect    Return low-level information on Docker objects
docker run -d -p 8001:8000 -v /var/run/docker.sock:/var/run/docker.sock -v yacht:/config selfhostedpro/yacht
  kill        Kill one or more running containers
</pre>
  load        Load an image from a tar archive or STDIN
 
  login      Log in to a Docker registry
'''[https://youtu.be/Nf7m3h11y-s CloudFlare DDNS]''' - Update CloudFlare with Your Dynamic IP Address
  logout      Log out from a Docker registry
 
  logs        Fetch the logs of a container
'''[https://youtu.be/nQMYfpCY310 WatchTower]'''. It has some bugs; for example, [https://github.com/containrrr/watchtower/issues/2126#issuecomment-3532628440 Error response from daemon: client version 1.25 is too old]
  pause      Pause all processes within one or more containers
 
  port        List port mappings or a specific mapping for the container
'''[https://youtu.be/ji0kgXhXR6g bitwardenrs]'''. Use the terminal to create a volume first. The port number is 8100. This is straightforward.
  ps          List containers
 
  pull        Pull an image or a repository from a registry
'''[https://youtu.be/-NyzdAYMarw Duplicati]''' for backup.
  push        Push an image or a repository to a registry
 
  rename      Rename a container
'''[https://fleet.linuxserver.io/image?name=linuxserver/photoshow photoshow]'''. It works. It has a slideshow button. PhotoShow only displays videos in WebM.
  restart    Restart one or more containers
 
   rm          Remove one or more containers
'''R'''. [https://hub.docker.com/_/r-base r-base] provide arm64 image but not not 32-bit arm architecture.
  rmi        Remove one or more images
<pre>
  run        Run a command in a new container
# 64-bit OS
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
docker pull r-base
  search      Search the Docker Hub for images
docker run -it --rm r-base   # enter R directly
  start      Start one or more stopped containers
</pre>
  stats      Display a live stream of container(s) resource usage statistics
 
  stop        Stop one or more running containers
'''rocker/rstudio''' DOES NOT work on arm64 even I can pull. ''WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested''
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
 
  top        Display the running processes of a container
I build a 32-bit armv7 image for r-base v4.0.2. This image works on either 32-bit or 64-bit arm OS (tested on 32-/64-bit Raspberry Pi and other 32-bit SBC devices).
  unpause    Unpause all processes within one or more containers
<pre>
  update      Update configuration of one or more containers
docker pull arraytools/r402armv7
  version    Show the Docker version information
docker run -it --rm arraytools/r402armv7 R
  wait        Block until one or more containers stop, then print their exit codes
docker pull r-base
# Using default tag: latest
# latest: Pulling from library/r-base
# no matching manifest for linux/arm/v7 in the manifest list entries
</pre>
 
== How and Why to Use A Remote Docker Host ==
* [https://www.cloudsavvyit.com/11185/how-and-why-to-use-a-remote-docker-host/ How and Why to Use A Remote Docker Host]
* [https://www.cloudsavvyit.com/12514/how-docker-contexts-let-you-work-with-multiple-hosts/ How Docker Contexts Let You Work with Multiple Hosts]


Run 'docker COMMAND --help' for more information on a command.
== Backup ==
</pre>
* [https://docs.docker.com/storage/volumes/#backup-restore-or-migrate-data-volumes Backup, restore, or migrate data volumes]
* [https://stackoverflow.com/a/28145912 Backup a running Docker container?]
* [https://www.maketecheasier.com/copy-move-docker-container-to-another-host/ How to Copy/Move a Docker Container to Another Host]
* [https://www.reddit.com/r/docker/comments/vi0o4k/comment/idbndut/?utm_source=share&utm_medium=web2x&context=3 Is backing up `/var/lib/docker/volumes` a good way to back up your Docker containers? If not, what is?]
* [https://www.howtogeek.com/how-i-moved-my-docker-server-to-a-new-system/ How I Moved My Docker Server to a New System]


=== Version, system information ===
= Usage =
Docker version
== Basics, docs, cheatsheet, introduction ==
<syntaxhighlight lang='bash'>
* https://docs.docker.com/articles/basics/
$ docker version
* [https://www.fosstechnix.com/docker-command-cheat-sheet/ 81 Docker Command Cheat Sheet with Description]
Client:
* https://coderwall.com/p/2es5jw/docker-cheat-sheet-with-examples
Version:           18.06.1-ce
* https://github.com/wsargent/docker-cheat-sheet
API version:       1.38
* [https://www.howtoforge.com/tutorial/how-to-use-docker-introduction/ How to use Docker in a practical way]
Go version:       go1.10.3
* https://hackernoon.com/introduction-to-docker-a7d9e1f6c0b3#.tezit0hkq
Git commit:       e68fc7a
* [http://www.cnblogs.com/wanliwang01/p/docker01.html Docker快速入门]
Built:             Tue Aug 21 17:24:51 2018
* [http://blog.myplanet.com/docker-the-fun-and-easy-way Docker: The Fun and Easy Way]
OS/Arch:          linux/amd64
* [https://www.r-bloggers.com/2023/06/a-gentle-introduction-to-docker/ A Gentle Introduction to Docker]. docker build & renv.
Experimental:      false


Server:
Note that we need '''sudo''' is needed unless it is on a Mac OS.
Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:      go1.10.3
  Git commit:      e68fc7a
  Built:            Tue Aug 21 17:23:15 2018
  OS/Arch:          linux/amd64
  Experimental:    false
</syntaxhighlight>


System information.  
If docker cannot find an image, it will try to pull it from its repository.
* what mode the Docker engine is operating in (swarm mode or not)
<pre>
* what storage drive is used for the union filesystem
$ sudo docker run -it ubuntu /bin/bash
* what version of the Linux kernel we have on our host
Unable to find image 'ubuntu' locally
* et al
Pulling repository ubuntu
<syntaxhighlight lang='bash'>
04c5d3b7b065: Download complete
$ docker system info
511136ea3c5a: Download complete
Containers: 2
c7b7c6419568: Download complete
Running: 0
70c8faa62a44: Download complete
Paused: 0
d735006ad9c1: Download complete
Stopped: 2
root@ec83b3ac878d:/#
Images: 10
</pre>
Server Version: 18.06.1-ce
 
Storage Driver: overlay2
{| class="wikitable"
Backing Filesystem: extfs
! purpose
Supports d_type: true
! command
Native Overlay Diff: true
|-
Logging Driver: json-file
| run a container
Cgroup Driver: cgroupfs
| docker container run -d -p 80:80 httpd
Plugins:
|-
Volume: local
| list running cotainer
Network: bridge host macvlan null overlay
| docker container ls
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
|-
Swarm: inactive
| view logs of Docker container
Runtimes: runc
| docker container logs cranky_cori
Default Runtime: runc
|-
Init Binary: docker-init
| identify Docker container process?
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
| docker container top cranky_cori
runc version: 69663f0bd4b60df09991c08812a60108003fa340
|-
init version: fec3683
| stop Docker container?
Security Options:
| docker container stop cranky_cori
  apparmor
|-
seccomp
| list stopped or not running Docker containers
  Profile: default
| docker container ls -a
Kernel Version: 4.15.0-33-generic
|-
Operating System: Ubuntu 18.04.1 LTS
| start Docker container
OSType: linux
| docker container start c46f2e9e4690
Architecture: x86_64
|-
CPUs: 4
| remove Docker container
Total Memory: 7.674GiB
| docker container rm cranky_cori
Name: t420s
|-
ID: VLWB:6BN3:U7KB:L4T4:GQIB:54F3:YZKJ:PAIR:HEUM:UQIC:XLZU:3IFJ
| list Docker images
Docker Root Dir: /var/lib/docker
| docker images
Debug Mode (client): false
|-
Debug Mode (server): false
| remove Docker image
Registry: https://index.docker.io/v1/
| docker rmi iman/touch
Labels:
|}
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false


WARNING: No swap limit support
=== Restart docker daemon ===
</syntaxhighlight>
When I try the Chap5 > Continuous integration (Jenkins) of the Docker Book, I found I cannot stop/kill the container. See others' report [https://github.com/docker/docker/issues/1906 here]. The solution is to restart the docker daemon.
 
<pre>
=== List resource consumption ===
sudo service docker start
<syntaxhighlight lang='bash'>
</pre>
$ docker system df
After that, I can stop and rm the container.
TYPE                TOTAL              ACTIVE              SIZE                RECLAIMABLE
<pre>
Images              10                  2                  2.58GB              1.519GB (58%)
sudo docker stop jenkins
Containers          2                  0                  304B                304B (100%)
sudo docker rm jenkins
Local Volumes      2                  0                  314.7MB            314.7MB (100%)
sudo docker ps -a
Build Cache        0                  0                  0B                  0B
</pre>


$ docker system df -v  # more detailed information
=== images vs containers ===
# We can use the information to clean up our system
</syntaxhighlight>
 
== [https://www.youtube.com/watch?v=umJYDAYxZys A brief intro to docker virtualization] ==
<pre>
<pre>
docker search --help
$ sudo docker images
docker search redis
REPOSITORY                    TAG                IMAGE ID            CREATED              VIRTUAL SIZE
docker search -s 100 redis
iman                          latest              6e0f5644b2fd        About a minute ago  460.4 MB
docker pull --help
iman/touch                    latest              77b9ac5951c2        4 minutes ago        460.4 MB
docker pull ubuntu # download all versions of ubuntu
<none>                        <none>              aaa75e64ddf0        5 weeks ago          188.3 MB
docker images    # available local container images
ouruser/sinatra                v2                  ea8c9f407a8d        5 weeks ago          447 MB
docker pull centos:latest
ubuntu                         14.04              ed5a78b7b42b        5 weeks ago          188.3 MB
docker run --help
ubuntu                         latest             ed5a78b7b42b        5 weeks ago          188.3 MB
cat /etc/issue   # look at the current distr name before running docker
eddelbuettel/docker-ubuntu-r   add-r-devel-san    3c19d078c5d9        3 months ago        460.4 MB
docker run -it centos:latest /bin/bash
hello-world                    latest             ef872312fe1b        4 months ago        910 B
                # create a container & execute as a sudo
training/sinatra              latest              f0f4ab557f95        8 months ago        447 MB


cat /etc/redhat-release
$ sudo docker ps -a
yum
CONTAINER ID IMAGE                                          COMMAND              CREATED        STATUS                  PORTS NAMES
cd /home
8fbdbcdb5126 iman/touch:latest                              "/bin/bash"          2 minutes ago  Exited (0) 2 minutes ago      thirsty_engelbart 
touch temp.txt
dc9e82f2c00a eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          9 minutes ago  Exited (0) 3 minutes ago      kickass_bardeen   
ls
532a90f36aa8 eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        happy_lalande     
exit
7634024ee0bf eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        insane_mclean     
 
14034a9720cb eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago   Exited (0) 18 hours ago        naughty_lumiere   
docker ps   # current running processes
ca90954628db eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          19 hours ago  Exited (130) 18 hours ago      sick_hawking       
docker ps -a # show all processes including closed
8bbdcb7c339f eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          19 hours ago  Exited (0) 19 hours ago        modest_davinci     
docker restart c85850ed0e13
e8e24f80f0dd aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      berserk_hodgkin   
docker ps   # container c85850ed0e13 is running
d41959e0eb55 aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      jovial_curie       
docker attach c85850ed0e13 # log into the system
b408c0e2805b aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      lonely_tesla       
72a551e4b492 ouruser/sinatra:v2                            "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        jolly_meitner     
75fd6cc4658b training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        evil_yalow         
cc8886f5a02e training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (130) 5 weeks ago      elegant_curie     
0585e4f5fecd eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        elated_euclid     
brb@brbweb4:~/Downloads$
</pre>


ls /home
When we want to delete a container, we use the container's '''CONTAINER ID''' or '''NAME''' (last column output from docker ps -a). But when we want to delete an image, we use the image's '''REPOSITORY''' or '''IMAGE ID''' (2nd column output from docker images)
exit
<pre>
$ sudo docker rm thirsty_engelbart  # iman/touch
$ sudo docker rm dc9e82f2c00a      # eddelbuettel/docker-ubuntu-r:add-r-devel-san
$ sudo docker ps -a  # check to see the container is gone now


docker ps -a
$ sudo docker rmi 6e0f5644b2fd
docker rm c85850ed0e13 # delete the container
$ sudo docker rmi iman/touch
$ sudo docker images  # check to see the images are gone now
</pre>
</pre>
Note: Following the [http://askubuntu.com/questions/505506/docker-how-to-get-bash-ssh-inside-runned-container-run-d discussion], using '''attach''' can only launch one instance of shell. If we use '''exec''', we can launch multiple instances.
 
=== Command line interface, CLI ===
https://docs.docker.com/engine/reference/commandline/cli/ Docker command line
<pre>
<pre>
sudo docker exec -i -t c85850ed0e13 bash #by ID
$ docker
or
$ sudo docker exec -i -t loving_heisenberg bash #by Name
</pre>


== docker pull ==
Usage: docker COMMAND
https://docs.docker.com/engine/reference/commandline/pull/


<syntaxhighlight lang='bash'>
A self-sufficient runtime for containers
$ docker pull ubuntu:zesty
$ docker run -ti --rm ubuntu:zesty /bin/bash
# lsb_release -a       
bash: lsb_release: command not found
# cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=17.04
DISTRIB_CODENAME=zesty
DISTRIB_DESCRIPTION="Ubuntu 17.04"
NAME="Ubuntu"
VERSION="17.04 (Zesty Zapus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 17.04"
VERSION_ID="17.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=zesty
UBUNTU_CODENAME=zesty
</syntaxhighlight>


=== Update/upgrade images ===
Options:
I have an image called 'rocker/tidyverse:latest' that was pulled sometime ago. I ran ''docker pull rocker/tidyverse:latest' again. It will pull the latest image. The old image was not deleted and it has a new tag '''<none>'''.
      --config string      Location of client config files (default "/home/brb/.docker")
 
  -D, --debug              Enable debug mode
[https://success.docker.com/article/how-to-remove-a-signed-image-with-a-none-tag How to remove a signed image with a <none> tag]
  -H, --host list          Daemon socket(s) to connect to
 
  -l, --log-level string  Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
Same thing happened today. I run ''docker pull r-base'' to upgrade my r-base from v3.6.3 to v4.0.0. After the upgrade, the old image has a tag '''<none>'''. I can use '''docker rmi''' command to remove the <none> image.
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string  Trust certs signed only by this CA (default "/home/brb/.docker/ca.pem")
      --tlscert string    Path to TLS certificate file (default "/home/brb/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/home/brb/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit


=== <none>:<none> images ===
Management Commands:
* [http://www.projectatomic.io/blog/2015/07/what-are-docker-none-none-images/ What are Docker <none>:<none> images? ]
  config      Manage Docker configs
* [https://docs.docker.com/engine/reference/commandline/images/#filtering docker images]
  container  Manage containers
  image      Manage images
  network    Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service    Manage services
  swarm      Manage Swarm
  system      Manage Docker
  trust      Manage trust on Docker images
  volume      Manage volumes


== Exit/detach from a container without stopping it ==
Commands:
<syntaxhighlight lang='bash'>
  attach      Attach local standard input, output, and error streams to a running container
$ docker container run -it ubuntu:latest /bin/bash
  build      Build an image from a Dockerfile
# Ctrl+p, Ctrl+q to exit the container without terminating it
  commit      Create a new image from a container's changes
$ docker ps -a # showing the container 70c5aceb5512 is running in the background
  cp          Copy files/folders between a container and the local filesystem
 
  create      Create a new container
# You can reattach your terminal to it with the "docker container exec" command
  diff        Inspect changes to files or directories on a container's filesystem
$ docker container exec -it 70c5aceb5512 bash
  events      Get real time events from the server
</syntaxhighlight>
  exec       Run a command in a running container
 
  export      Export a container's filesystem as a tar archive
== Dockerizing Applications/Detached mode ==
  history    Show the history of an image
<pre>
  images      List images
$ sudo docker run -d --name insane_babbage ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
  import      Import the contents from a tarball to create a filesystem image
$ sudo docker ps -l
  info        Display system-wide information
$ sudo docker logs insane_babbage
  inspect    Return low-level information on Docker objects
$ sudo docker stop insane_babbage
  kill        Kill one or more running containers
$ sudo docker ps
  load        Load an image from a tar archive or STDIN
</pre>
  login      Log in to a Docker registry
The -d flag tells Docker to run the container and put it in the background, to daemonize it.
  logout      Log out from a Docker registry
 
  logs        Fetch the logs of a container
According to https://docs.docker.com/engine/reference/run/#detached-vs-foreground, 
  pause      Pause all processes within one or more containers
'''containers started in detached mode exit when the root process used to run the container exits, unless you also specify the --rm option. If you use -d with --rm, the container is removed when it exits or when the daemon exits, whichever happens first.'''
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart    Restart one or more containers
  rm          Remove one or more containers
  rmi        Remove one or more images
  run        Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start      Start one or more stopped containers
  stats      Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag        Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top        Display the running processes of a container
  unpause    Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version    Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes


=== Automatically restart after reboot ===
Run 'docker COMMAND --help' for more information on a command.
https://stackoverflow.com/questions/18786054/how-to-auto-restart-a-docker-container-after-a-reboot-in-coreos
</pre>
 
Add a '''--restart=always''' parameter. It will always restart a stopped container unless it has been explicitly stopped, such as via a "docker container stop" command. See the following
* https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart
* https://docs.docker.com/engine/admin/start-containers-automatically/#restart-policy-details


=== Version, system information ===
Docker version
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
$ docker run -d --restart always myCustomeDocker
$ docker version
Client:
Version:          18.06.1-ce
API version:      1.38
Go version:        go1.10.3
Git commit:        e68fc7a
Built:            Tue Aug 21 17:24:51 2018
OS/Arch:          linux/amd64
Experimental:      false


$ docker container run --name neverdie -it --restart always ubuntu /bin/bash
Server:
# exit
Engine:
$ docker ps -a  # the container is still ther
  Version:          18.06.1-ce
$ docker stop neverdie
  API version:      1.38 (minimum version 1.12)
$ docker ps -a
  Go version:      go1.10.3
  Git commit:      e68fc7a
  Built:            Tue Aug 21 17:23:15 2018
  OS/Arch:          linux/amd64
  Experimental:    false
</syntaxhighlight>
</syntaxhighlight>


== Working with Containers ==
System information.
<pre>
* what mode the Docker engine is operating in (swarm mode or not)
$ sudo docker run -i -t ubuntu /bin/bash
* what storage drive is used for the union filesystem
$ sudo docker version
* what version of the Linux kernel we have on our host
$ sudo docker
* et al
$ sudo docker attach --help
</pre>
 
=== Alpine image ===
* [https://docs.docker.com/samples/library/alpine/ A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!]
* [http://containertutorials.com/alpine/get_started.html Container Tutorials > Getting Started with Alpine]
* [https://nickjanetakis.com/blog/the-3-biggest-wins-when-using-alpine-as-a-base-docker-image The 3 Biggest Wins When Using Alpine as a Base Docker Image]
* [https://www.cyberciti.biz/faq/10-alpine-linux-apk-command-examples/ 10 Alpine Linux apk Command Examples]
: <syntaxhighlight lang='bash'>
apk add htop
</syntaxhighlight>
 
=== Running a Web Application ===
<pre>
$ sudo docker run -d -P training/webapp python app.py
</pre>
 
Alpine linux is 6MB. It is a good OS to run a web application. See the demo [https://youtu.be/BFKNwr_wllc here].
 
=== Viewing our Web Application Container ===
<pre>
$ sudo docker ps -l
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
</pre>
 
=== Container networking===
* https://docs.docker.com/network/
* [https://docs.docker.com/network/network-tutorial-standalone/#use-user-defined-bridge-networks Use user-defined bridge networks]
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
$ docker network create MyNewNetworkName
$ docker system info
$ docker network ls
Containers: 2
NETWORK ID          NAME                DRIVER              SCOPE
Running: 0
abae0010bf2c        MyNewNetworkName    bridge              local
Paused: 0
bf4e73473028        bridge             bridge              local
Stopped: 2
7dac0804bc33        host                host                local
Images: 10
dbe7f0daef6d        none                null                local
Server Version: 18.06.1-ce
$ docker network remove MyNewNetworkName
Storage Driver: overlay2
# OR docker network rm MyNewNetworkName
Backing Filesystem: extfs
</syntaxhighlight>
Supports d_type: true
* https://youtu.be/Ox5mZBwc92E
Native Overlay Diff: true
 
Logging Driver: json-file
=== [https://docs.docker.com/network/host/ Host network] ===
Cgroup Driver: cgroupfs
If you use the '''host''' network driver for a container, that container’s network stack is not isolated from the Docker host. For instance, if you run a container which binds to port 80 and you use host networking, the container’s application will be available on port 80 on the host’s IP address.
Plugins:
 
Volume: local
=== ping, ifconfig and ip commands not found in Ubuntu container ===
Network: bridge host macvlan null overlay
<syntaxhighlight lang='bash'>
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
apt update
Swarm: inactive
apt install iputils-ping  # ping
Runtimes: runc
apt install net-tools    # ifconfig
Default Runtime: runc
apt install iproute2      # ip
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
apparmor
seccomp
  Profile: default
Kernel Version: 4.15.0-33-generic
Operating System: Ubuntu 18.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.674GiB
Name: t420s
ID: VLWB:6BN3:U7KB:L4T4:GQIB:54F3:YZKJ:PAIR:HEUM:UQIC:XLZU:3IFJ
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
 
WARNING: No swap limit support
</syntaxhighlight>
</syntaxhighlight>


=== Network Port Shortcut ===
=== List resource consumption ===
<pre>
$ sudo docker port nostalgic_morse 5000
</pre>
 
=== Viewing the Web Application's Logs ===
<pre>
$ sudo docker logs -f nostalgic_morse
</pre>
 
=== Looking at our Web Application Container's processes ===
<pre>
$ sudo docker top nostalgic_morse
</pre>
 
=== Inspecting our Web Application Container ===
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
$ sudo docker inspect nostalgic_morse
$ docker system df
</syntaxhighlight>
TYPE                TOTAL              ACTIVE              SIZE                RECLAIMABLE
Images              10                  2                  2.58GB              1.519GB (58%)
Containers          2                  0                  304B                304B (100%)
Local Volumes      2                  0                  314.7MB            314.7MB (100%)
Build Cache        0                  0                  0B                  0B


=== Obtain the container's IP address, log into a running server ===
$ docker system df -v  # more detailed information
<syntaxhighlight lang='bash'>
# We can use the information to clean up our system
$ docker inspect <container id> | grep "IPAddress"
</syntaxhighlight>
</syntaxhighlight>


Then to log into a running server, use
== [https://www.youtube.com/watch?v=umJYDAYxZys A brief intro to docker virtualization] ==
<syntaxhighlight lang='bash'>
<pre>
$ docker exec -it <contianer id> bash
docker search --help
</syntaxhighlight>
docker search redis
docker search -s 100 redis
docker pull --help
docker pull ubuntu # download all versions of ubuntu
docker images    # available local container images
docker pull centos:latest
docker run --help
cat /etc/issue  # look at the current distr name before running docker
docker run -it centos:latest /bin/bash
                # create a container & execute as a sudo


=== docker exec: SSH into a running container ===
cat /etc/redhat-release
Run a command in a running container
yum
cd /home
touch temp.txt
ls
exit


* [https://docs.docker.com/engine/reference/commandline/exec/ Usage]: <syntaxhighlight lang='bash'>
docker ps  # current running processes
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
docker ps -a # show all processes including closed
</syntaxhighlight>
docker restart c85850ed0e13
* Examples: <syntaxhighlight lang='bash'>
docker ps  # container c85850ed0e13 is running
$ docker exec -d ubuntu_bash touch /tmp/execWorks # do st in the background
docker attach c85850ed0e13 # log into the system


$ docker exec -it ubuntu_bash bash
ls /home
exit


$ docker exec -it -e VAR=1 ubuntu_bash bash # set an environment variable
docker ps -a
docker rm c85850ed0e13 # delete the container
</pre>
Note: Following the [http://askubuntu.com/questions/505506/docker-how-to-get-bash-ssh-inside-runned-container-run-d discussion], using '''attach''' can only launch one instance of shell. If we use '''exec''', we can launch multiple instances.
<pre>
sudo docker exec -i -t c85850ed0e13 bash #by ID
or
$ sudo docker exec -i -t loving_heisenberg bash #by Name
</pre>


$ docker exec -it ubuntu_bash pwd
== Rootless mode ==
$ docker exec -it -w /root ubuntu_bash pwd # change the working directory
<ul>
</syntaxhighlight>
<li>[https://docs.docker.com/engine/security/rootless/ Run the Docker daemon as a non-root user (Rootless mode)]
* The data dir is set to '''~/.local/share/docker''' by default. The data dir should not be on NFS.
<li>Setup on Ubuntu 22.04
<syntaxhighlight lang='sh'>
curl -fsSL https://get.docker.com | bash
sudo apt install -y uidmap
dockerd-rootless-setuptool.sh install
nano ~/.bashrc


=== docker cp ===
source ~/.bashrc
* https://docs.docker.com/engine/reference/commandline/cp/
* https://linuxhandbook.com/docker-cp-example/


Copy files/folders between a container and the local filesystem.
systemctl --user start docker
systemctl --user enable docker
sudo loginctl enable-linger $(whoami)


=== Restart an exited Container ===
docker run hello-world
* https://docs.docker.com/engine/reference/commandline/start/
docker run --rm -ti r-base:4.4.1
* https://www.linuxnix.com/docker-start-exited-container/
</syntaxhighlight>
<pre>
<li>Unfortunately, Rocker/rstudio does not work. I am not able to log in using username/password. It keeps saying incorrect username/password.
$ sudo docker start nostalgic_morse
<li>'''Limitations''':
OR
* Performance Overhead
$ sudo docker restart nostalgic_morse
** OverlayFS Limitations: Rootless Docker uses fuse-overlayfs instead of OverlayFS by default, which can be slower.
</pre>
** Resource Limits: The performance might be slightly lower compared to running Docker with root privileges due to additional user namespace operations.
* Network Restrictions
** Network Drivers: Only the bridge and host network drivers are supported. macvlan and overlay network drivers are not supported.
** Port Binding: Binding to ports below 1024 is not allowed. Only non-privileged ports (1024 and above) can be used.
* File System
** Volume Permissions: Issues with file permissions can arise when mounting volumes from the host, as the files created by rootless Docker processes will be owned by the user running Docker, not root.
** NFS and Other Filesystems: Certain filesystems like NFS might have compatibility issues with rootless Docker due to permission and ownership constraints.
* Compatibility
** Certain Features: Some Docker features might not be fully supported or behave differently. For example, checkpoint/restore and cgroup v1 are not supported.
** Security Features: Some security features like AppArmor, SELinux, and seccomp might have limited functionality or require additional configuration.
* Configuration Complexity
* Troubleshooting
<li>[https://serverfault.com/a/1128797 What's the difference between rootless Docker, running a container as a non-root user, and Podman?]
<li>[https://itnext.io/docker-running-in-rootless-mode-bdbcfc728b3a Docker Running In Rootless Mode]
<li>[https://mohitgoyal.co/2021/04/14/going-rootless-with-docker-and-containers/ Going rootless with Docker and Containers]
<li>[https://www.liquidweb.com/kb/how-to-docker-rootless-containers/ How to Run Rootless Docker Containers]
<li>[https://ostechnix.com/rootless-docker-debian-ubuntu-linux/ How To Migrate To Rootless Docker In Debian And Ubuntu Linux]
</ul>


=== Inspect container images and their metadata ===
== docker pull ==
[https://microbadger.com/images/rocker/r-base MicroBadger]
https://docs.docker.com/engine/reference/commandline/pull/


=== Know the container size ===
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker ps -s
$ docker pull ubuntu:zesty
</syntaxhighlight>
$ docker run -ti --rm ubuntu:zesty /bin/bash
[https://github.com/docker/docker.github.io/issues/1520#issuecomment-305179362 Meaning of two sizes]
# lsb_release -a       
* The "size" information shows the amount of data (on disk) that is used for the writable layer of each container
bash: lsb_release: command not found
* The "virtual size" is the amount of disk-space used for the read-only image data used by the container.
# cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=17.04
DISTRIB_CODENAME=zesty
DISTRIB_DESCRIPTION="Ubuntu 17.04"
NAME="Ubuntu"
VERSION="17.04 (Zesty Zapus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 17.04"
VERSION_ID="17.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=zesty
UBUNTU_CODENAME=zesty
</syntaxhighlight>


=== Removing our Web Application Container ===
=== Update/upgrade images ===
<syntaxhighlight lang='bash'>
* I have an image called 'rocker/tidyverse:latest' that was pulled sometime ago. I ran ''docker pull rocker/tidyverse:latest' again. It will pull the latest image. The old image was not deleted and it has a new tag '''<none>'''.
$ sudo docker stop nostalgic_morse
* [https://success.docker.com/article/how-to-remove-a-signed-image-with-a-none-tag How to remove a signed image with a <none> tag]
$ sudo docker rm nostalgic_morse
* Same thing happened today. I run ''docker pull r-base'' to upgrade my r-base from v3.6.3 to v4.0.0. After the upgrade, the old image has a tag '''<none>'''. I can use '''docker rmi''' command to remove the <none> image.
* [https://bytefreaks.net/applications/docker/how-to-update-all-pulled-docker-images-that-are-tagged-as-latest How to update all pulled Docker images that are tagged as latest]
* [https://vsupalov.com/docker-latest-tag/ What's Wrong With The Docker :latest Tag?] '''Do not run any container with the latest tag.'''
* [https://www.reddit.com/r/docker/comments/vjx9ct/how_to_upgrade_container_properly/ How to upgrade container properly?]  "docker-compose pull" to update all your service and "docker-compose up -d" to start them all. docker swarm is even better because you can achieve zero downtme rolling upgrades.
* The following two are equivalent
:<syntaxhighlight lang='bash'>
docker compose pull && docker compose up -d
docker compose up --pull always -d
</syntaxhighlight>
</syntaxhighlight>


Note: Always remember that deleting a container is final!
=== <none>:<none> images ===
* [http://www.projectatomic.io/blog/2015/07/what-are-docker-none-none-images/ What are Docker <none>:<none> images? ]
* [https://docs.docker.com/engine/reference/commandline/images/#filtering docker images]


=== Dockerize an SSH service ===
== Exit/detach from a container without stopping it ==
https://docs.docker.com/engine/examples/running_ssh_service/#environment-variables
<syntaxhighlight lang='bash'>
$ docker container run -it ubuntu:latest /bin/bash
# Ctrl+p, Ctrl+q to exit the container without terminating it
$ docker ps -a # showing the container 70c5aceb5512 is running in the background
 
# You can reattach your terminal to it with the "docker container exec" command
$ docker container exec -it 70c5aceb5512 bash
</syntaxhighlight>
 
== How to start a stopped Docker container with a different command ==
[https://stackoverflow.com/a/39329138 How to start a stopped Docker container with a different command?]


=== Remove old docker containers ===
== Clean shutdown DOCKER containers before reboot ==
[http://stackoverflow.com/questions/17236796/how-to-remove-old-docker-io-containers This post] on stackoverflow.com.
* [https://forum.openmediavault.org/index.php?thread/22012-clean-shutdown-docker-containers-before-reboot-or-shutdown-omv/ Clean shutdown DOCKER containers before reboot or shutdown OMV] '''systemctl stop docker'''
<pre>
* [https://linuxhandbook.com/docker-stop-container/ How to Stop Docker Containers] '''docker ps -q | xargs docker stop'''
$ sudo docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs --no-run-if-empty sudo docker rm
</pre>


Similarly to remove all exited containers
== Dockerizing Applications/Detached mode ==
<pre>
<pre>
$ sudo docker ps -a | grep Exit | awk '{print $1}' | xargs sudo docker rm
$ sudo docker run -d --name insane_babbage ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
$ sudo docker ps -l
$ sudo docker logs insane_babbage
$ sudo docker stop insane_babbage
$ sudo docker ps
</pre>
</pre>
The -d flag tells Docker to run the container and put it in the background, to daemonize it.


To kill/stop (not delete) all running containers
According to https://docs.docker.com/engine/reference/run/#detached-vs-foreground, 
<pre>
'''containers started in detached mode exit when the root process used to run the container exits, unless you also specify the --rm option. If you use -d with --rm, the container is removed when it is stopped, exits or when the daemon exits, whichever happens first.'''
$ sudo docker kill $(sudo docker ps -q)
</pre>


'''To delete all stopped containers'''
=== Automatically restart after reboot ===
<pre>
https://stackoverflow.com/questions/18786054/how-to-auto-restart-a-docker-container-after-a-reboot-in-coreos
$ sudo docker rm $(sudo docker ps -a -q)
 
OR
Add a '''--restart=always''' parameter. It will always restart a stopped container unless it has been explicitly stopped, such as via a "docker container stop" command. See the following
$ sudo docker rm `sudo docker ps -a -q`
* https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart
* https://docs.docker.com/engine/admin/start-containers-automatically/#restart-policy-details
 
<syntaxhighlight lang='bash'>
$ docker run -d --restart always myCustomeDocker
 
$ docker container run --name neverdie -it --restart always ubuntu /bin/bash
# exit
$ docker ps -a  # the container is still ther
$ docker stop neverdie
$ docker ps -a  
</syntaxhighlight>
 
== Working with Containers ==
<pre>
$ sudo docker run -i -t ubuntu /bin/bash
$ sudo docker version
$ sudo docker
$ sudo docker attach --help
</pre>
</pre>


It is also helpful to create bash aliases for these commands by editing ~/.bash_aliases file.
=== Environment variables ===
* [https://www.baeldung.com/ops/docker-container-environment-variables Passing Environment Variables to Docker Containers]
* [https://docs.docker.com/compose/environment-variables/ Environment variables in Compose]
* An example: [https://github.com/tcardonne/docker-github-runner Docker github runner]
 
=== Select columns from "docker ps" output ===
Below will output (and reorder) the NAME, CONTAINER ID, IMAGE and Ports columns only from regular "docker ps" output. The COMMAND, CREATED, and STATUS columns will be skipped.


=== docker create vs docker run ===
<nowiki>
https://stackoverflow.com/questions/37744961/docker-run-vs-create
alias dockerps='docker ps --format "{{printf \"%-12s\" .Names}}{{printf \"%-15s\" .ID}}{{printf \"%-30s\" .Image}}{{printf \"%-25s\" .Ports}}"'
</nowiki>


'''docker create''' is similar to '''docker run -d''' except the container is never started.
=== Docker container ID ===
* The full container ID is a hexadecimal string of 64 characters.
* The minimum number of characters required for a Docker ID is 4.
* We can use a shorter ID in docker command if that ID uniquely determined the container. For example, '''docker exec -it 9608 bash''' or even '''docker exec -it 9 bash''' works.


== Volume ==
=== Alpine image ===
* https://docs.docker.com/storage/volumes/
* [https://www.makeuseof.com/alpine-linux-explained/ Alpine Linux: A Breath of Fresh Mountain Air for Linux Experts]
* [https://docs.docker.com/engine/reference/commandline/volume_create/ docker volume create] documentation
* [https://docs.docker.com/samples/library/alpine/ A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!]
* If we try to mount an empty dir on the host to a non-empty dir (eg mediawiki/extensions) in a container, it will mess up.
* [http://containertutorials.com/alpine/get_started.html Container Tutorials > Getting Started with Alpine]
* [https://www.melvinvivas.com/using-docker-data-volume-with-a-mysql-container/ Using Docker Data Volume with a MySQL container]
* [https://nickjanetakis.com/blog/the-3-biggest-wins-when-using-alpine-as-a-base-docker-image The 3 Biggest Wins When Using Alpine as a Base Docker Image]
* [https://codeblog.dotsandbrackets.com/persistent-data-docker-volumes/ Persistent data in Docker volumes]
* [https://www.cyberciti.biz/faq/10-alpine-linux-apk-command-examples/ 10 Alpine Linux apk Command Examples]
: <syntaxhighlight lang='bash'>
apk add htop
</syntaxhighlight>


=== Inspect the 'Mountpoint' of a volume ===
=== Running a Web Application ===
<syntaxhighlight lang='bash'>
<pre>
$ docker volume create crv
$ sudo docker run -d -P training/webapp python app.py
$ docker volume ls
</pre>


$ docker run -d \
Alpine linux is 6MB. It is a good OS to run a web application. See the demo [https://youtu.be/BFKNwr_wllc here].
    --name mycloud \
    -p 81:80 \
    -v apps:/var/www/html/custom_apps \
    nextcloud


# docker inspect is not quite useful. It does not show how the volume was created
=== Viewing our Web Application Container ===
# But we can examine (ls, du, ...) the directory contents
<pre>
$ docker inspect apps 
$ sudo docker ps -l
[
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
    {
</pre>
        "CreatedAt": "2018-10-23T09:41:52-04:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/apps/_data",
        "Name": "apps",
        "Options": null,
        "Scope": "local"
    }
]
</syntaxhighlight>


=== Remove an an unnamed volume ===
=== Monitor, Check container status (docker status) - CPU, Memory usage ===
If you created an unnamed volume, it can be deleted at the same time as the container with the -v flag. Note that this only works with unnamed volumes.
<ul>
<li>[https://www.cloudytuts.com/tutorials/docker/how-to-check-memory-and-cpu-utilization-of-docker-container/ How to Check Memory and CPU Utilization of Docker Container], [https://www.howtoforge.com/how-to-check-docker-container-ram-and-cpu-usage/ How to Check Docker Container RAM and CPU Usage]
<pre>
docker stats          # ctrl + c to quit
docker stats CONTAINER # multiple 'ctrl + c' to quit
docker stats --no-stream
docker stats --no-stream CONTAINER
</pre>
<li>[https://github.com/ColinFay/dockerstats docker stats]
</ul>


=== Container networking===
<ul>
<li>https://docs.docker.com/network/
<li>[https://docs.docker.com/network/network-tutorial-standalone/#use-user-defined-bridge-networks Use user-defined bridge networks]
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker rm -v container_name
$ docker network create MyNewNetworkName
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
abae0010bf2c        MyNewNetworkName    bridge              local
bf4e73473028        bridge              bridge              local
7dac0804bc33        host                host                local
dbe7f0daef6d        none                null                local
$ docker network remove MyNewNetworkName
# OR docker network rm MyNewNetworkName
</syntaxhighlight>
</syntaxhighlight>
<li>https://youtu.be/Ox5mZBwc92E
<li>Use '''dig''' to find out the IP and run DNS query. [https://jvns.ca/blog/2021/01/04/docker-compose-is-nice/ Docker Compose: a nice way to set up a dev environment]
<li>[https://dev.to/leandronsp/mastering-the-docker-networking-2h57 Mastering the Docker networking]
</ul>


If the volume is named, it stays present. To remove a named volume, use '''docker volume rm volume_name''' .
=== [https://docs.docker.com/network/host/ Host network] ===
* If you use the '''host''' network driver for a container, that container’s network stack is not isolated from the Docker host. For instance, if you run a container which binds to port 80 and you use host networking, the container’s application will be available on port 80 on the host’s IP address.
* One good example is if I want to use tailscale network from my host in Uptime Kuma container. See [https://wiki.taichimd.us/view/Docker_Applications#Uptime_Kuma HERE].
* Considerations. While host networking can be powerful, it's important to consider:
** Security implications: Host networking reduces network isolation, potentially increasing security risks.
** Port conflicts: Services using host networking may conflict with other applications running on the host machine.
** Platform limitations: Host network mode only works on Linux hosts, not on Docker Desktop for Mac or Windows.


=== [https://docs.docker.com/storage/volumes/#start-a-container-with-a-volume Start a container with a volume] ===
=== ping, ifconfig and ip commands not found in Ubuntu container ===
{| class="wikitable"
<syntaxhighlight lang='bash'>
! --mount
apt update
! -v
apt install iputils-ping  # ping
|-
apt install net-tools    # ifconfig
| docker run -d \
apt install iproute2      # ip
--name devtest \ <br/>
</syntaxhighlight>
--mount source=myvol2,target=/app \  <br/>
 
nginx:latest
=== Network Port Shortcut ===
| docker run -d \
<pre>
--name devtest \  <br/>
$ sudo docker port nostalgic_morse 5000
-v myvol2:/app \  <br/>
</pre>
nginx:latext
|}
Note
* '''target''' in "--mount" can be replaced by '''destination''' or '''dst'''.
* To use a read-only volume, add the ''',readonly''' option in "--mount" or the ''':ro''' option in "-v".


=== A simple example ===
=== Access Ports on the Host from a Docker Container ===
From the book "Learn Docerk -Fundamentals of Docker 18.x". Chap 5. Data Volumes and System Management > Creating and mounting data volumes.
[https://www.cloudsavvyit.com/6940/how-to-access-ports-on-the-host-from-a-docker-container/ How to Access Ports on the Host from a Docker Container]


<syntaxhighlight lang='bash'>
=== Multiple NICs ===
# Create a volume
[https://www.reddit.com/r/docker/comments/vi2alw/containers_in_docker_to_use_public_ip_addresses/ containers in docker to use public ip addresses directly]
docker volume create my-data
docker volume inspect my-data
# The host folder can be found in the output under 'Mountpoint'
# In my case,
#        "Mountpoint": "/var/lib/docker/volumes/my-data/_data",


# Mount a volume into a container
=== Viewing the Web Application's Logs ===
docker run --name test -it -v my-data:/data alpine /bin/sh
<ul>
# cd /data
<li>[https://linuxiac.com/dozzle-real-time-docker-logs-viewer/ Installing Dozzle: A Superb Real-Time Docker’s Logs Viewer], [https://github.com/amir20/dozzle Dozzle] docker image.
# echo 'some data' > data.txt
<li>Command line
# echo 'more data' > data2.txt
<pre>
# exit
$ sudo docker logs -f nostalgic_morse
docker inspect my-data
</pre>
sudo ls /var/lib/docker/volumes/my-data/_data
</ul>
# We can even try to output the content of say, the second file:
sudo cat /var/lib/docker/volumes/my-data/_data/data2.txt
# We can create a new file in this folder from the host and then use the volume with another container
echo "the file is created on host" > sudo tee /var/lib/docker/volumes/my-data/_data/host-data
# Let's delete the test container and run another one
docker rm test


# This time we are mounting our volume to a different container folder
=== Clear Logs of Running Docker Containers ===
docker run --name test2 -it -v my-data:/app/data centos:7 /bin/bash
* [https://www.howtogeek.com/devops/how-to-clear-logs-of-running-docker-containers/ How to Clear Logs of Running Docker Containers]
# We are able to see three files:
* [https://linuxiac.com/reducing-docker-logs-file-size/ Reducing Docker Logs Size: A Practical Guide to Log Management]
# ls /app/data


# Remove volumes
=== Looking at our Web Application Container's processes ===
docker volume rm my-data # Or
<pre>
docker volume rm $(docker volume ls -q)
$ sudo docker top nostalgic_morse
</pre>
 
=== Inspect the linux distribution of the base image ===
<syntaxhighlight lang='bash'>
$ docker inspect rocker/shiny:4.4.0
</syntaxhighlight>
In the '''Labels''' section of the output, we see the following line:
<pre>
"org.opencontainers.image.base.name": "docker.io/library/ubuntu:jammy"
</pre>
This indicates that the base image for rocker/shiny:4.4.0 is bsaed on Ubuntu Jammy.


# Remove all running containers to clean up the system,
=== Inspecting our Web Application Container ===
docker rm -f $(docker ls -aq)
<syntaxhighlight lang='bash'>
$ docker inspect nostalgic_morse
</syntaxhighlight>
</syntaxhighlight>


=== Sharing data between containers ===
=== Obtain the container's IP address, log into a running server ===
PS. '''Portainer''' web interface can show the IP addresses.
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker run -it --name writer -v shared-data:/data alpine /bin/sh
$ docker inspect <container id> | grep "IPAddress"
# create a file inside it
# echo 'my sample file' > /data/sample.txt
# exit
docker run -it --name reader -v shared-data:/app/data:ro ubuntu:17.04 /bin/bash
# ls -l /app/data
</syntaxhighlight>
</syntaxhighlight>


=== Using host volumes ===
We don't need the IP address if we just want to log into a running server,
Use volumes that mount a specific host folder
* It may be possible for the "docker volume" command to mount a local directory to a volume. See [https://docs.docker.com/engine/reference/commandline/volume_create/#examples examples] in the "docker volume create" documentation.
* Specifying a directory name instead of giving a volume name in the "docker run" 's '''-v''' option
* Since we are specifying a directory name instead of letting docker to create a new volume, "docker volume ls" will not getting a new volume
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker run -it --name test -v $(pwd)/src:/app/src alpine /bin/sh
$ docker exec -it <contianer id> bash
</syntaxhighlight>


# Make a sample to demonstrate how that works
=== How to Secure Docker’s TCP Socket ===
mkdir ~/my-web; cd ~/my-web
[https://www.cloudsavvyit.com/15079/how-to-secure-dockers-tcp-socket-with-tls/ How to Secure Docker’s TCP Socket with TLS]
echo "<h1>My website</h1>" > index.html


# Create 'Dockerfile'
=== docker attach ===
echo -e 'FROM nginx:alpine
Suppose I run ''docker run -it --user rstudio bioconductor/bioconductor_docker:devel R'' and I use ''q()'' to quit the container. The container is still there. To re-enter the R in the container, I use
COPY . /usr/share/nginx/html' > Dockerfile
<pre>
docker start XXXXXXXX    # restart it in the background
docker attach XXXXXXXX  # reattach the terminal to a running container
</pre>
If we want the latest created container, then we use
<pre>
docker start `docker ps -q -l` && docker attach `docker ps -q -l`
</pre>
 
=== docker exec: SSH into a running container ===
Run a command in a running container
<ul>
<li>[https://docs.docker.com/engine/reference/commandline/exec/ Usage]: <syntaxhighlight lang='bash'>
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
</syntaxhighlight>
<li>Examples: <syntaxhighlight lang='bash'>
$ docker exec -d ubuntu_bash touch /tmp/execWorks # do st in the background
 
$ docker exec -it ubuntu_bash bash


docker image build -t my-website:1.0 .
$ docker exec -it -e VAR=1 ubuntu_bash bash # set an environment variable
docker run -d -p 8080:80 --name my-site my-website:1.0


# Open http://localhost:8080. It looks good
$ docker exec -it ubuntu_bash pwd
# Now modify index.html and refresh the website. It does not refresh
$ docker exec -it -w /root ubuntu_bash pwd # change the working directory
# Let's stop and rm the container and rebuild using a volume
docker rm -f my-site
docker run -d -v $(pwd):/usr/share/nginx/html \
  -p 8080:80 --name my-site my-website:1.0
# Now any changes on index.html will refresh on the website
</syntaxhighlight>
</syntaxhighlight>
<li>[https://www.cloudsavvyit.com/14541/how-to-run-a-command-on-a-running-docker-container/ How to Run a Command on a Running Docker Container]
<li>[https://thenewstack.io/how-to-use-the-docker-exec-command/ How to Use the Docker exec Command]. nginx container is used as an example.
<pre>
docker run --name docker-nginx -p 8080:80 -d nginx


=== Define volumes in images ===
# method 1. Access the Running Container’s Shell
A few samples of volume definition
docker exec -it ID /bin/bash
<pre>
  apt-get update
VOLUME /app/data
  apt-get upgrade -y
VOLUME /app/data, /app/profiles, /app/config
  exit
VOLUME {"/app/data", "/app/profiles", "/app/config"]
 
# method 2. Run a Command from Outside the Container
docker exec ID apt-get update &amp;&amp; apt-get upgrade
 
docker exec ID cat /usr/share/nginx/html/index.html
docker cp index.html ID:/usr/share/nginx/html/
docker exec ID cat /usr/share/nginx/html/index.html
</pre>
</pre>
The first line defines a single volume to be mounted at ''/app/data''.
</ul>
 
=== docker cp ===
* https://docs.docker.com/engine/reference/commandline/cp/
* https://linuxhandbook.com/docker-cp-example/  
 
Copy files/folders between a container and the local filesystem.


We can use the ''docker image inspect'' command to get information about the volumes defined in the Dockerfile.
=== Restart an exited Container ===
<syntaxhighlight lang='bash'>
* https://docs.docker.com/engine/reference/commandline/start/
docker image pull mongo:3.7
* https://www.linuxnix.com/docker-start-exited-container/
docker image inspect --format='{{json .ContainerConfig.Volumes}}' \
<pre>
      mongo:3.7 | jq
$ docker start nostalgic_morse
# {
OR
"/data/configdb": {},
$ docker restart nostalgic_morse
"/data/db": {}
</pre>
# }
For an interactive container, use '''docker start -ai CONTAINER''' which is equal to run "docker start CONTAINER" and "docker attach CONTAINER".


# now run an instance of MongoDB and inspect the volume information
=== Rename a container ===
docker run --name my-mongo -d mongo:3.7
[https://docs.docker.com/engine/reference/commandline/container_rename/ docker container rename]
docker inspect --format '{{json .Mounts}}' my-mongo | jq
<pre>
# [
docker container rename CONTAINER NEW_NAME
#  {
</pre>
#    "Type": "volume",
 
#    "Name": "535e0138b9a32e89f71380e9e73bb0de64ce0d1cad78fcda0ec1d49e11d76d7a",
=== Inspect container images and their metadata ===
#    "Source": "/var/lib/docker/volumes/535e0138b9a32e89f71380e9e73bb0de64ce0d1.../_data",
* [https://www.cloudsavvyit.com/14663/how-to-inspect-a-docker-images-content-without-starting-a-container/ How to Inspect a Docker Image’s Content Without Starting a Container]
#    "Destination": "/data/configdb",
* [https://microbadger.com/images/rocker/r-base MicroBadger]
#    "Driver": "local",
 
#    "Mode": "",
=== Know the container size ===
#    "RW": true,
<syntaxhighlight lang='bash'>
#    "Propagation": ""
docker ps -s
#  },
#  {
#    "Type": "volume",
# SKIP
</syntaxhighlight>
</syntaxhighlight>
[https://github.com/docker/docker.github.io/issues/1520#issuecomment-305179362 Meaning of two sizes]
* The "size" information shows the amount of data (on disk) that is used for the writable layer of each container
* The "virtual size" is the amount of disk-space used for the read-only image data used by the container.


=== Differences between VOLUME and '-v|--volume' ===
=== Removing our Web Application Container ===
https://stackoverflow.com/a/25312719
<syntaxhighlight lang='bash'>
$ sudo docker stop nostalgic_morse
$ sudo docker rm nostalgic_morse
</syntaxhighlight>


=== Backup and restore container ===
Note: Always remember that deleting a container is final!
* https://docs.docker.com/storage/volumes/#backup-restore-or-migrate-data-volumes
* [https://stackoverflow.com/a/28145912 Backup a running Docker container?]


=== Container Memory Limits, Setting Available CPUs, Allocating memory and CPU ===
=== Dockerize an SSH service ===
* [https://medium.com/@nitesh.turaga/how-i-use-bioconductor-with-docker-part-2-more-memory-faster-bioconductor-with-docker-fd7e69dce2bf How I use Bioconductor with Docker (part 2): More memory, faster Bioconductor with Docker]
https://docs.docker.com/engine/examples/running_ssh_service/#environment-variables
: <syntaxhighlight lang='bash'>
docker run \
    -rm \ ## Automatically remove the container when it exits
    --memory=6g \ ## memory limit
    --cpus=1.5 \ ## number of CPUs
    -v /shared/data-store:/home/rstudio/data \
    -v /shared/library-store:/usr/local/lib/R/host-site-library \
    -e PASSWORD=bioc \
    -p 8787:8787 \
        bioconductor/bioconductor_full:devel
</syntaxhighlight>
* [https://docs.docker.com/docker-for-mac/ Get started with Docker Desktop for Mac], [https://docs.docker.com/docker-for-windows/ Windows]
* [https://docs.docker.com/config/containers/resource_constraints/ Limit a container's resources]
* [https://blog.docker.com/2018/12/top-5-post-docker-container-java/ TOP 5 BLOG OF 2018: IMPROVED DOCKER CONTAINER INTEGRATION WITH JAVA 10]


== Work with container images ==
=== Remove old docker containers ===
* https://docs.docker.com/userguide/dockerimages/
[http://stackoverflow.com/questions/17236796/how-to-remove-old-docker-io-containers This post] on stackoverflow.com.
<pre>
$ sudo docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs --no-run-if-empty sudo docker rm
</pre>


=== Create an image interactively using '''commit''' - Example 1 ===
Similarly to remove all exited containers
The example is from the book 'Learn Docker - Fundamentals of Docker 18.x'.
<pre>
<syntaxhighlight lang='bash'>
$ sudo docker ps -a | grep Exit | awk '{print $1}' | xargs sudo docker rm
docker container run -it --name sample alpine /bin/sh
</pre>
# apk update && apk add iputils
# ping 127.0.0.1
# exit
docker container ls -a | grep sample
docker container diff sample
</syntaxhighlight>
We can now use the ''docker container commit'' command to persist our modifications and create a new image from them
<syntaxhighlight lang='bash'>
docker container commit sample my-alpine
docker images ls
</syntaxhighlight>


If we want to see how our custom image has been built, we can use the ''history'' command as follows:
To kill/stop (not delete) all running containers
<syntaxhighlight lang='bash'>
<pre>
docker image history my-alpine
$ sudo docker kill $(sudo docker ps -q)
# IMAGE              CREATED              CREATED BY                                      SIZE    COMMENT
</pre>
# 0f105057899b        About a minute ago  /bin/sh                                        1.55MB             
# 196d12cf6ab1        4 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B                 
# <missing>          4 weeks ago          /bin/sh -c #(nop) ADD file:25c10b1d1b41d46a1…  4.41MB
</syntaxhighlight>
The first layer in the preceding list is the one we just created by adding the iputils package.


=== Create an image interactively using '''commit''' - Example 2 ===
'''To delete all stopped containers'''
* [http://www.techrepublic.com/article/how-to-commit-changes-to-a-docker-image/ How to commit changes to a docker image]
<pre>
$ sudo docker rm $(sudo docker ps -a -q)
OR
$ sudo docker rm `sudo docker ps -a -q`
</pre>


<span style="color: red">Note that it is better/necessary to put the Dockerfile in an empty directory</span> to avoid the problem of taking a long time to build the image (''sending build context to Docker daemon ...GB '') since it will grab files from the current directory.
It is also helpful to create bash aliases for these commands by editing ~/.bash_aliases file.


<syntaxhighlight lang='bash'>
=== docker create vs docker run ===
sudo docker search sinatra
https://stackoverflow.com/questions/37744961/docker-run-vs-create
sudo docker pull training/sinatra
sudo docker run -t -i training/sinatra /bin/bash
sudo docker commit -m="Added json gem" -a="Kate Smith" 0b2616b0e5a8 ouruser/sinatra:v2
sudo docker images


mkdir sinatra
'''docker create''' is similar to '''docker run -d''' except the container is never started.
cd sinatra
touch Dockerfile
sudo docker build -t="ouruser/sinatra:v2" .
sudo docker push ouruser/sinatra
sudo docker rmi training/sinatra
</syntaxhighlight>


* I get an error when I try to launch sinatra on my 32-bit ubuntu (Docker can only be installed through apt-get on 32-bit)
=== Retrieve docker run command ===
https://stackoverflow.com/a/32774347. See the github page of [https://github.com/lavie/runlike runlike]. So it is better to put the docker run in a stack. Then for example the Portainer has an Editor tab to show the [https://docs.docker.com/compose/compose-file/ compose file].
<pre>
<pre>
$ sudo docker run -t -i training/sinatra /bin/bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
2014/12/31 02:43:26 exec format error
    assaflavie/runlike -p CONTAINER_NAME
</pre>
</pre>
The '''-p''' option splits the output into pretty lines.
=== docker run -it and -d together ===
* [https://stackoverflow.com/a/41918607 Practically, what is the difference between docker run -dit(-itd) vs docker run -d?]
* [https://github.com/docker/docker.github.io/issues/10632 "docker run -dit" vs "docker run -d" #10632]
=== How to Modify the Configuration of Running Docker Containers ===
[https://www.cloudsavvyit.com/15254/how-to-modify-the-configuration-of-running-docker-containers/ How to Modify the Configuration of Running Docker Containers]


=== How to copy Docker images from one host to another without using a repository ===
== Volume ==
https://stackoverflow.com/questions/23935141/how-to-copy-docker-images-from-one-host-to-another-without-using-a-repository
* https://docs.docker.com/storage/volumes/
<syntaxhighlight lang='bash'>
* [https://docs.docker.com/engine/reference/commandline/volume_create/ docker volume create] documentation
docker save -o out.tar <image name>
* If we try to mount an empty dir on the host to a non-empty dir (eg mediawiki/extensions) in a container, it will mess up.
# Or better to compress the file
* [https://www.melvinvivas.com/using-docker-data-volume-with-a-mysql-container/ Using Docker Data Volume with a MySQL container]
docker save <docker image name> | gzip > out.tar.gz
* [https://www.cloudsavvyit.com/7500/what-are-docker-volumes-and-how-do-you-use-them/ What Are Docker Volumes, and How Do You Use Them?]
 
=== Examples of host's volume locations ===
<pre>
/home/$USER/docker/$PROJECT/$SUB-DIRECTORY
</pre>
 
=== PUID, PGID, share volume permission/owner ===
<ul>
<li>[https://docs.linuxserver.io/general/understanding-puid-and-pgid Understanding PUID and PGID] (or the [https://github.com/linuxserver/docker-documentation/blob/master/general/understanding-puid-and-pgid.md source])
<li>How to Create Users in Linux (for testing the case the user id is not 1000)
<syntaxhighlight lang='sh'>
sudo adduser jane # create /home/jane
sudo id jane      # it should not be 1000
                  # so we can do some testing
sudo nano /etc/sudoers # add jane
su - jane    # switch to /home/jane
# Add a user to the docker group and immediately apply the changes without requiring the user to log out and back in
sudo usermod -aG docker $USER; newgrp docker
 
# Test some examples
docker run --rm -ti --user docker -v "$(pwd)":/workspace r-base
> setwd("/workspace")
Error in setwd("/workspace") : cannot change working directory
 
docker run --rm -ti --user $(id -u):$(id -g) -v "$(pwd)":/workspace r-base
# telling Docker to run the container as your current host user.
> setwd("/workspace")
# Writing works. But the file owner is an id, not my user name
</syntaxhighlight>
<li>You should use the -e PUID and -e PGID options when creating a container from a Docker image to map the container’s internal user to a user on the host machine. This is useful because Docker runs all of its containers under the '''root''' user domain, which means that processes running inside your containers also run as '''root'''. '''This kind of elevated access is not ideal for day-to-day use and can potentially give applications access to things they shouldn’t.''' By using PUID and PGID, you can ensure that files and directories created during the container’s lifespan are owned by a user on the host machine instead of root.
<li>'''Please note that not all Docker images support the PUID and PGID environment variables. The Docker image must be designed to use these variables.''' If you’re using an image that doesn’t support these variables, you may need to create a Dockerfile to build a new image that does.
<li>The following works. The '''--user''' option is a built-in Docker feature that sets the user (and optionally the group) that is used to run the container. This option works regardless of whether the Docker image uses any specific environment variables. PS. "docker" user has been defined in the r-base's [https://github.com/rocker-org/rocker/blob/master/r-base/4.4.0/Dockerfile Dockerfile].
<syntaxhighlight lang='sh'>
docker run --rm -ti --user docker \
  -v "$(pwd)":/workspace r-base
> setwd("/workspace")
> save(iris, file="iris.rda")
> system("ls -lt") # docker docker instead of $USER $USER
> unlink("iris.rda")
</syntaxhighlight>
<li>Similarly, the '''--user''' option works with rocker/rstudio image and ubuntu.
<syntaxhighlight lang='sh'>
docker run --rm -ti --user rstudio \
  -v "$(pwd)":/workspace rocker/rstudio R
> setwd("/workspace")
> save(iris, file="iris.rda")
> system("ls -lt")
> unlink("iris.rda")
</syntaxhighlight>
</syntaxhighlight>
And restore
Note that the prompt is '''$''' rather than '''#'''.
<syntaxhighlight lang='bash'>
{{Pre}}
docker load -i out.tar
docker run --rm -it -v $(pwd):/home --user ubuntu \
# Or decompress the file
  ubuntu bash
docker load < out.tar.gz
$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev)
$ cd /home
$ echo "newfile" > newfile
</pre>
<syntaxhighlight lang='sh'>
docker run --rm -it -v $(pwd):/home --user "$(id -u):$(id -g)" \
  ubuntu bash
$ cd /home
$ echo "newfile" > newfile
</syntaxhighlight>
<li>In the article [https://github.com/rocker-org/rocker/wiki/Sharing-files-with-host-machine Sharing files with host machine] from the Rocker's project, users are instructed to use '''-e USERID''' variable if the host machine user has a UID other than 1000. But the generated file 'iris.rda' from the following example is still owned by root:(
<syntaxhighlight lang='sh'>
docker run --rm -ti -v "$(pwd)":/workspace -e USERID=$UID rocker/rstudio R
</syntaxhighlight>
</syntaxhighlight>
<li>(Cont.) however, if we run the above command as a daemon and '''log in using the user "rstudio" ''', it works even we don't specify the "-e USERID" option. The lesson is we should use the user defined in the docker image.
<pre>
docker run --rm -v "$(pwd)":/workspace -p PASSWORD=123 rocker/rstudio
</pre>
Notice the prompt is '''#''' rather than '''$''' and the user id is 0.
<pre>
docker run --rm -it -v $(pwd):/home -e PUID=1000 -e PGID=1000 \
  ubuntu bash
# id
uid=0(root) gid=0(root) groups=0(root)
</pre>
<li>In this video [https://youtu.be/oHC6J_aN4eQ?t=137 How to Install Calibre on OMV and Docker], it uses the command '''id admin'''  where "admin" is the portainer user to get PUID (of "admin") and PGID (of "users") to find out the two ids.
<li>Shiny application with output files, [https://gist.github.com/arraytools/08f9d0ba651b504176d77fbeab72e501 github].
</ul>
=== Back Up Your Docker Volumes ===
[https://www.howtogeek.com/devops/how-to-back-up-your-docker-volumes/ How to Back Up Your Docker Volumes]


=== Resources allocated to a container using docker? ===
=== Two ways to achieve persistent data ===
https://stackoverflow.com/questions/16084741/how-do-i-set-resources-allocated-to-a-container-using-docker
* [https://codeblog.dotsandbrackets.com/persistent-data-docker-volumes/ Persistent data in Docker volumes]
* [https://www.cloudsavvyit.com/3588/how-to-deal-with-docker-container-persistence-and-storage/ How to Deal with Docker Container Persistence and Storage]. Docker has two ways to achieve persistence: '''volume mounts''', and '''bind mounts'''.


=== hub.docker.com ===
=== Inspect the 'Mountpoint' of a volume ===
* Note that Dockerfile is optional on https://registry.hub.docker.com.
<syntaxhighlight lang='bash'>
* For free account, we can have only [https://docs.docker.com/docker-hub/repos/ 1 free private repository]. If we want to create a new repository online, we can
$ docker volume create crv
: <syntaxhighlight lang='bash'>
$ docker volume ls
docker tag local-image:tagname new-repo:tagname
 
docker push new-repo:tagname
$ docker run -d \
</syntaxhighlight>
    --name mycloud \
* [https://stackoverflow.com/a/28349540 How to push a docker image to a private repository]
    -p 81:80 \
* [https://registry.hub.docker.com/repos/rocker/ rocker]. The Dockerfile is included there. Question: how to automatically build the image rather than uploading pre-built image binaries to Docker Hub?
    -v apps:/var/www/html/custom_apps \
* Search all repositories related to [https://registry.hub.docker.com/search?q=r&searchfield= R]
    nextcloud
* [http://phusion.github.io/baseimage-docker/ baseimage-docker]. I can use ping command without special argument when I start phusion/baseimage.
 
: <syntaxhighlight lang='bash'>
# docker inspect is not quite useful. It does not show how the volume was created
docker pull phusion/baseimage
# But we can examine (ls, du, ...) the directory contents
docker run -ti phusion/baseimage /bin/bash
$ docker inspect apps 
[
    {
        "CreatedAt": "2018-10-23T09:41:52-04:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/apps/_data",
        "Name": "apps",
        "Options": null,
        "Scope": "local"
    }
]
</syntaxhighlight>
</syntaxhighlight>
* https://dockerfile.github.io/ which includes dockerfiles for different purposes. The ubuntu-desktop one also works well (client needs a vnc viewer in order to see the desktop).


=== Set up a private Docker registry ===
=== Remove an an unnamed volume ===
* https://docs.docker.com/registry/ <syntaxhighlight lang='bash'>
I you want to automatically removes volumes when a container is removed, you can use the '''--rm''' flag when starting the container with the "docker run" command. This flag tells Docker to automatically remove the container and any '''anonymous volumes''' associated with it when the container exits. However, this flag does not affect '''named volumes'''.
docker run -d -p 5000:5000 --name registry registry:2
 
docker pull ubuntu
If you created an unnamed volume, it can be deleted at the same time as the container with the -v flag. Note that this only works with unnamed volumes.
docker image tag ubuntu localhost:5000/myfirstimage
<syntaxhighlight lang='bash'>
docker push localhost:5000/myfirstimage
docker rm -v container_name
docker pull localhost:5000/myfirstimage
docker container stop registry && docker container rm -v registry
</syntaxhighlight>
* https://docs.docker.com/registry/deploying/
* [https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-14-04 Ubuntu 14.04] from digitalocean
* [https://www.howtoforge.com/tutorial/how-to-setup-private-docker-registry-on-ubuntu-1804-lts/ How to Setup Private Docker Registry on Ubuntu 18.04 LTS]
* [http://www.thegeekstuff.com/2017/01/secure-docker-registry/ How to Setup Secure Docker Registry on Linux using TLS SSL Certificate]
* List repositories in the local registry. [https://docs.docker.com/registry/spec/api/#listing-image-tags Docker Registry HTTP API V2] and [https://stackoverflow.com/a/14978657 HTTP POST and GET using cURL in Linux].
: <syntaxhighlight lang='bash'>
$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:5000/v2/_catalog
$ OR
$ curl -H "Accept: application/xml" -H "Content-Type: application/json" -X GET http://localhost:5000/v2/_catalog
</syntaxhighlight>
</syntaxhighlight>


=== Google cloud registry ===
If the volume is named, it stays present. To remove a named volume, use '''docker volume rm volume_name''' .
[https://seandavi.github.io/2019/02/using-google-cloud-registry-for-private-docker-images/ Using google cloud registry for private docker images]
 
=== Volumes created in docker-compose ===
When you use '''docker-compose''' to create and manage containers, volumes are handled slightly differently than when using the '''docker run''' command.
 
In a "docker-compose.yml" file, you can specify named volumes using the volumes key at the top level of the file. These volumes are created when you run docker-compose up and are not automatically removed when you stop or remove the containers using docker-compose down.


== Dockerfile ==
If you want to remove '''named volumes''' created by docker-compose, you can use the '''-v''' flag with the '''docker-compose down''' command. Here’s an example command that stops and removes all containers defined in a docker-compose.yml file and also removes any named volumes:
* [https://docs.docker.com/reference/builder/ Dockerfile Reference]
<pre>
* [https://www.digitalocean.com/community/tutorials/docker-explained-using-dockerfiles-to-automate-building-of-images Using Dockerfiles to Automate Building of Images] from digitalocean.com.
docker-compose down -v
* <strike><span style="color: red">Remember to put the Dockerfile in an empty directory</span></strike>.
</pre>
* [https://medium.com/better-programming/what-goes-into-a-dockerfile-ff0ace591060 What goes into a Dockerfile]
This command stops and removes all containers defined in the docker-compose.yml file and also removes any named volumes specified in the file. All data stored in the volumes will be permanently deleted.
* Keywords
** FROM. If we want to start from scratch, we can use ''FROM scratch''.
** RUN. The argument for RUN is any valid Linux command.
** [https://docs.docker.com/engine/reference/builder/#user USER]. This is useful if we want to create new files with a non-root owner privilege. For example, new files created under a binding directory with a non-root user ownership will belong to the current user in the host system. [https://github.com/jlintusaari/R-docker-report.git Here] is an example where we use Rmarkdown to create pdf output. The generated pdf file should not be own by root.
** COPY & ADD.
*** "COPY . /app" will copy all files and folders from the current directory recursively to the /app folder. We can use "ADD" too but "ADD" will automatically unpack tarballs. See [https://stackoverflow.com/a/24958548 What is the difference between the `COPY` and `ADD` commands in a Dockerfile?]
*** "ADD sample.tar /app/bin" will unpack the ''sample.tar' file into the target folder
*** "ADD <nowiki>http://example.com/sample.txt</nowiki> /data/" will copy the remote file sample.txt into the target file
** WORKDIR. Define the working directory or context that is used when a container is run from the image.
** CMD & ENTRYPOINT. These two are actually definitions of what will happen when a container is started from the image.
*** Use CMD without ENTRYPOINT: "CMD command param1 param2". This form is called the '''shell''' form.
*** If we use ENTRYPOINT + CMD, ENTRYPOINT defines the command and CMD defines parameters. The example above will run ''ping 8.8.8.8 -c 3''. This form is called the '''exec''' form.
* [https://github.com/jamtur01/dockerbook-code The Docker Book]
* [https://github.com/rocker-org/rocker rocker (R and RStudio)]
* [https://github.com/Bioconductor/bioc_docker/tree/master/out Bioconductor]


=== Examples of Dockerfile ===
'''Anonymous volumes''' created by docker-compose are automatically removed when you stop and remove the containers using docker-compose down, even if you don’t use the -v flag.
* [https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers Only the instructions RUN, COPY, ADD create layers.]
* A sample. Six layers (lines). The first line is the Base Layer.
<pre>
FROM python:2.7
RUN mkdir -p /app
WORKDIR /app
COPY ./requirements.txt /app/
RUN pip install -r requirements.txt
CMD ["python", "main.py"]
</pre>
* Another example
<pre>
FROM alpine:latest
ENTRYPOINT ["ping"]
CMD ["8.8.8.8", "-c", "3"]
</pre>


=== How to use Dockerfile ===
=== [https://docs.docker.com/storage/volumes/#start-a-container-with-a-volume Start a container with a volume] ===
https://docs.docker.com/engine/reference/commandline/build/
{| class="wikitable"
! --mount
! -v
|-
| docker run -d \
--name devtest \ <br/>
--mount source=myvol2,target=/app \  <br/>
nginx:latest
| docker run -d \
--name devtest \  <br/>
-v myvol2:/app \  <br/>
nginx:latext
|}
Note
* '''target''' in "--mount" can be replaced by '''destination''' or '''dst'''.
* To use a read-only volume, add the ''',readonly''' option in "--mount" or the ''':ro''' option in "-v".
* We cannot use "~/" to represent a local directory under HOME. We have to specify a full path in '''docker run'''.


<syntaxhighlight lang='bash'>
=== A simple example ===
docker build -t [myname] .
From the book "Learn Docerk -Fundamentals of Docker 18.x". Chap 5. Data Volumes and System Management > Creating and mounting data volumes.
# Multiple tags
docker build -t arraytools/biospear:latest -t arraytools/biospear:3.6.0 .
</syntaxhighlight>


In the above example, we can create the image by
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker image build -t pinger .
# Create a volume
</syntaxhighlight>
docker volume create my-data
We can run a container from the pinger image
docker volume inspect my-data
<syntaxhighlight lang='bash'>
# The host folder can be found in the output under 'Mountpoint'
docker container run --rm -it pinger
# In my case,
</syntaxhighlight>
#        "Mountpoint": "/var/lib/docker/volumes/my-data/_data",


=== ENTRYPOINT and CMD ===
# Mount a volume into a container
* If your container acts like a command-line program, you can use '''ENTRYPOINT'''. If you are unsure, you can use '''CMD'''.
docker run --name test -it -v my-data:/data alpine /bin/sh
* [https://blog.codeship.com/understanding-dockers-cmd-and-entrypoint-instructions/ Understanding Docker’s CMD and ENTRYPOINT Instructions]. It shows how to supply arguments to the command we like to execute in the container.
# cd /data
* [https://dille.name/blog/2019/12/05/creating-advanced-entrypoints-for-containers/ Creating Advanced Entrypoints for Containers]
# echo 'some data' > data.txt
# echo 'more data' > data2.txt
# exit
docker inspect my-data
sudo ls /var/lib/docker/volumes/my-data/_data
# We can even try to output the content of say, the second file:
sudo cat /var/lib/docker/volumes/my-data/_data/data2.txt
# We can create a new file in this folder from the host and then use the volume with another container
echo "the file is created on host" > sudo tee /var/lib/docker/volumes/my-data/_data/host-data
# Let's delete the test container and run another one
docker rm test


'''The advantage of using ENTRYPOINT + CMD''' (exec form) instead of using '''CMD''' alone (shell form) is we can override the ''CMD'' part that I have defined in the Dockerfile.
# This time we are mounting our volume to a different container folder
<syntaxhighlight lang='bash'>
docker run --name test2 -it -v my-data:/app/data centos:7 /bin/bash
docker container run --rm -it pinger -w 5 127.0.0.1
# We are able to see three files:
# ping the loopback for 5 seconds
# ls /app/data
</syntaxhighlight>
 
# Remove volumes
docker volume rm my-data # Or
docker volume rm $(docker volume ls -q)
 
# Remove all running containers to clean up the system,
docker rm -f $(docker ls -aq)
</syntaxhighlight>
 
=== Sharing data between containers ===
[https://www.cloudsavvyit.com/15112/how-to-share-data-between-docker-containers/ How to Share Data Between Docker Containers]


If we want to overwrite what's defined in the ''ENTRYPOINT'' in the Dockerfile, we need to use the ''--entrypoint'' parameter.
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker container run --rm -it --entrypoint /bin/sh pinger
docker run -it --name writer -v shared-data:/data alpine /bin/sh
# we'll be inside the container. Type exit to leave the container
# create a file inside it
# echo 'my sample file' > /data/sample.txt
# exit
docker run -it --name reader -v shared-data:/app/data:ro ubuntu:17.04 /bin/bash
# ls -l /app/data
</syntaxhighlight>
</syntaxhighlight>


When we use the '''shell''' form, the '''ENTRYPOINT''' is have the default value of ''/bin/sh -c'' and whatever is the value of ''CMD'' will be passed as a string to the shell command.
=== Using host volumes ===
Use volumes that mount a specific host folder
* It may be possible for the "docker volume" command to mount a local directory to a volume. See [https://docs.docker.com/engine/reference/commandline/volume_create/#examples examples] in the "docker volume create" documentation.
* Specifying a directory name instead of giving a volume name in the "docker run" 's '''-v''' option
* Since we are specifying a directory name instead of letting docker to create a new volume, "docker volume ls" will not getting a new volume
<syntaxhighlight lang='bash'>
docker run -it --name test -v $(pwd)/src:/app/src alpine /bin/sh


=== Temporary failure resolving 'deb.debian.org' when running "docker build" ===
# Make a sample to demonstrate how that works
Add "--net=host" to the docker build command. See [https://stackoverflow.com/questions/24991136/docker-build-could-not-resolve-archive-ubuntu-com-apt-get-fails-to-install-a Docker build “Could not resolve 'archive.ubuntu.com'” apt-get fails to install anything]
mkdir ~/my-web; cd ~/my-web
echo "<h1>My website</h1>" > index.html


=== Best practices for writing Dockerfiles ===
# Create 'Dockerfile'
* https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
echo -e 'FROM nginx:alpine
* [https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices/ Intro Guide to Dockerfile Best Practices]
COPY . /usr/share/nginx/html' > Dockerfile


=== Use multi-stage builds ===
docker image build -t my-website:1.0 .
https://docs.docker.com/develop/develop-images/multistage-build/
docker run -d -p 8080:80 --name my-site my-website:1.0


With multi-stage builds, we have a single Dockerfile containing multiple FROM instructions. Each FROM instruction is a new '''build stage''' that can easily COPY artifacts from previous '''stages'''.
# Open http://localhost:8080. It looks good
# Now modify index.html and refresh the website. It does not refresh
# Let's stop and rm the container and rebuild using a volume
docker rm -f my-site
docker run -d -v $(pwd):/usr/share/nginx/html \
  -p 8080:80 --name my-site my-website:1.0
# Now any changes on index.html will refresh on the website
</syntaxhighlight>


[https://github.com/nigelpoulton/atsea-sample-shop-app An example] from the "Docker Deep Dive" book.
=== Define volumes in images ===
 
A few samples of volume definition
=== tag after image was built ===
<pre>
<pre>
$ docker tag <imageID> <newName>/<repoName>:<tagName>
VOLUME /app/data
VOLUME /app/data, /app/profiles, /app/config
VOLUME {"/app/data", "/app/profiles", "/app/config"]
</pre>
</pre>
The first line defines a single volume to be mounted at ''/app/data''.


=== About storage drivers ===
We can use the ''docker image inspect'' command to get information about the volumes defined in the Dockerfile.
https://docs.docker.com/storage/storagedriver/#sharing-promotes-smaller-images
<syntaxhighlight lang='bash'>
docker image pull mongo:3.7
docker image inspect --format='{{json .ContainerConfig.Volumes}}' \
      mongo:3.7 | jq
# {
#  "/data/configdb": {},
#  "/data/db": {}
# }


=== Dockerfile in One Line ===
# now run an instance of MongoDB and inspect the volume information
<pre>
docker run --name my-mongo -d mongo:3.7
FROM ubuntu
docker inspect --format '{{json .Mounts}}' my-mongo | jq
</pre>
# [
Using This simple Dockerfile and the docker command '''sudo docker build -t scooby_snacks .''' will result in
#  {
<pre>
#    "Type": "volume",
$ sudo docker images
#    "Name": "535e0138b9a32e89f71380e9e73bb0de64ce0d1cad78fcda0ec1d49e11d76d7a",
REPOSITORY          TAG                IMAGE ID            CREATED            VIRTUAL SIZE
#    "Source": "/var/lib/docker/volumes/535e0138b9a32e89f71380e9e73bb0de64ce0d1.../_data",
ubuntu              15.04              2427658c75a1        42 hours ago        117.5 MB
#    "Destination": "/data/configdb",
ubuntu              vivid              2427658c75a1        42 hours ago        117.5 MB
#    "Driver": "local",
ubuntu              vivid-20150218      2427658c75a1        42 hours ago        117.5 MB
#    "Mode": "",
ubuntu              utopic-20150211    78949b1e1cfd        42 hours ago        194.4 MB
#   "RW": true,
ubuntu              utopic              78949b1e1cfd        42 hours ago        194.4 MB
#    "Propagation": ""
ubuntu              14.10              78949b1e1cfd        42 hours ago        194.4 MB
#  },
ubuntu              14.04              2d24f826cb16        42 hours ago        188.3 MB
#  {
ubuntu              14.04.2            2d24f826cb16        42 hours ago        188.3 MB
#    "Type": "volume",
ubuntu              trusty              2d24f826cb16        42 hours ago        188.3 MB
# SKIP
ubuntu              trusty-20150218.1  2d24f826cb16        42 hours ago        188.3 MB
</syntaxhighlight>
ubuntu              latest              2d24f826cb16        42 hours ago        188.3 MB
 
scooby_snacks      latest              2d24f826cb16        42 hours ago        188.3 MB
=== Differences between VOLUME and '-v|--volume' ===
ubuntu              precise            1f80e9ca2ac3        42 hours ago        131.5 MB
https://stackoverflow.com/a/25312719
ubuntu              precise-20150212   1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              12.04.5            1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              12.04              1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              14.04.1            5ba9dab47459        3 weeks ago        188.3 MB
ubuntu              12.10              c5881f11ded9        8 months ago        172.2 MB
ubuntu              quantal            c5881f11ded9        8 months ago        172.2 MB
ubuntu              13.04              463ff6be4238        8 months ago        169.4 MB
ubuntu              raring              463ff6be4238        8 months ago        169.4 MB
ubuntu              13.10              195eb90b5349        8 months ago        184.7 MB
ubuntu              saucy              195eb90b5349        8 months ago        184.7 MB
ubuntu              10.04              3db9c44f4520        10 months ago      183 MB
ubuntu              lucid              3db9c44f4520        10 months ago      183 MB
</pre>


== Run a shell script on host ==
=== Container Memory Limits, Setting Available CPUs, Allocating memory and CPU ===
* https://docs.docker.com/engine/reference/commandline/run/
* [https://medium.com/@nitesh.turaga/how-i-use-bioconductor-with-docker-part-2-more-memory-faster-bioconductor-with-docker-fd7e69dce2bf How I use Bioconductor with Docker (part 2): More memory, faster Bioconductor with Docker]
* [https://serverfault.com/questions/806812/docker-run-bash-script-then-remove-container This post] and [https://stackoverflow.com/questions/32163955/how-to-run-shell-script-on-host-from-docker-container this one]
: <syntaxhighlight lang='bash'>
<pre style="white-space: pre-wrap; /* CSS 3 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* IE 5.5+ */ " >
docker run \
$ docker run -v /path/to/sample_script.sh:/sample_script.sh \
    -rm \ ## Automatically remove the container when it exits
  --rm ubuntu bash sample_script.sh
    --memory=6g \ ## memory limit
    --cpus=1.5 \ ## number of CPUs
    -v /shared/data-store:/home/rstudio/data \
    -v /shared/library-store:/usr/local/lib/R/host-site-library \
    -e PASSWORD=bioc \
    -p 8787:8787 \
        bioconductor/bioconductor_full:devel
</syntaxhighlight>
* [https://docs.docker.com/docker-for-mac/ Get started with Docker Desktop for Mac], [https://docs.docker.com/docker-for-windows/ Windows]
* [https://docs.docker.com/config/containers/resource_constraints/ Limit a container's resources]
* [https://blog.docker.com/2018/12/top-5-post-docker-container-java/ TOP 5 BLOG OF 2018: IMPROVED DOCKER CONTAINER INTEGRATION WITH JAVA 10]
* [https://www.jottr.org/2022/04/22/parallelly-1.31.1/ parallelly 1.31.1: Better at Inferring Number of CPU Cores with Cgroups and Linux Containers]
* [https://www.thorsten-hans.com/limit-memory-for-docker-containers Docker Container Memory Limits Explained]
* [https://www.howtogeek.com/devops/how-to-set-a-memory-limit-for-docker-containers/ How to Set a Memory Limit for Docker Containers]
 
== Work with container images ==
* https://docs.docker.com/userguide/dockerimages/
 
=== List images by size or name ===
<pre>
# by size
docker images --format "{{.ID}}\t{{.Size}}\t{{.Repository}}" | sort -k 2 -h


# GATK container example
# by name
# First we log in interactive and see where is the default location (/usr in this case)
docker images --format "{{.ID}}\t{{.Size}}\t{{.Repository}}" | sort -k 3  
$ docker run --rm -i -t broadinstitute/gatk3:3.8-0 bash
</pre>
$ cat > tmp.sh << EOF
 
> pwd
=== List specific columns ===
> ls
> java -jar GenomeAnalysisTK.jar --version
> EOF
$ docker run --rm -v $(pwd):/usr/my broadinstitute/gatk3:3.8-0 bash my/tmp.sh
# ALTERNATIVELY, WE CAN PUT OUR SCRIPT IN THE TOP DIRECTORY (Hopefully the name is not duplicated)
$ docker run --rm -v $(pwd)/tmp.sh:/tmp.sh broadinstitute/gatk3:3.8-0 bash /tmp.sh
</pre>
* https://askubuntu.com/questions/890533/how-can-i-run-docker-commands-after-docker-run-from-a-script (need to leave a container open)
<pre>
<pre>
docker run -d -v$(pwd):/my SOMEIMAGE bash
docker images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}'
docker exec -d Test bash /my/script.sh
</pre>
</pre>
* Create a Dockerfile https://forums.docker.com/t/how-to-run-bash-command-after-startup/21631/2


== Link containers together ==
=== Create an image interactively using '''commit''' - Example 1 ===
* https://docs.docker.com/userguide/dockerlinks/
The example is from the book 'Learn Docker - Fundamentals of Docker 18.x'.
* [https://hub.docker.com/r/simplyintricate/mediawiki/ Mediawiki example]
<syntaxhighlight lang='bash'>
docker container run -it --name sample alpine /bin/sh
# apk update && apk add iputils
# ping 127.0.0.1
# exit
docker container ls -a | grep sample
docker container diff sample
</syntaxhighlight>
We can now use the ''docker container commit'' command to persist our modifications and create a new image from them
<syntaxhighlight lang='bash'>
docker container commit sample my-alpine
docker images ls
</syntaxhighlight>


== Manage data in containers ==
If we want to see how our custom image has been built, we can use the ''history'' command as follows:
* https://docs.docker.com/storage/volumes/
<syntaxhighlight lang='bash'>
* https://codereviewvideos.com/course/docker-tutorial-for-beginners/video/part-2-docker-volumes-volumes
docker image history my-alpine
 
# IMAGE              CREATED              CREATED BY                                      SIZE    COMMENT
== Assign a static IP to a container ==
# 0f105057899b        About a minute ago  /bin/sh                                        1.55MB             
* https://stackoverflow.com/questions/27937185/assign-static-ip-to-docker-container <syntaxhighlight lang='bash'>
# 196d12cf6ab1        4 weeks ago          /bin/sh -c #(nop) CMD ["/bin/sh"]              0B                 
# Step 1. create you own docker network (mynet123)
# <missing>          4 weeks ago          /bin/sh -c #(nop) ADD file:25c10b1d1b41d46a1…  4.41MB
docker network create --subnet=172.18.0.0/16 mynet123
# Step 2. simply run the image (I'll take ubuntu as example)
docker run --rm --net mynet123 --ip 172.18.0.22 -it ubuntu bash
# Check in the container shell
# Note that the container CAN access internet
apt install net-tools; ifconfig
exit
</syntaxhighlight>
</syntaxhighlight>
* https://docs.docker.com/engine/reference/commandline/network_create/#bridge-driver-options
The first layer in the preceding list is the one we just created by adding the iputils package.
* [https://stackoverflow.com/questions/25529386/how-can-i-set-a-static-ip-address-in-a-docker-container Try using the --net=host option] (no a new IP was allocated; not a good solution)


== Firewall ==
=== Create an image interactively using '''commit''' - Example 2 ===
[https://community.rstudio.com/t/rstudio-server-not-loading-taking-too-long-to-respond-in-browser/20786 Rstudio server not loading, taking too long to respond in browser]. On Ubuntu run ''sudo ufw allow PORTNUMBER''.
* [https://www.cloudsavvyit.com/15489/how-to-create-a-docker-image-from-a-running-container/ How to Create a Docker Image From a Running Container]. Commit messages are displayed when you use the '''docker history''' command to view the layers in an image.  
* [http://www.techrepublic.com/article/how-to-commit-changes-to-a-docker-image/ How to commit changes to a docker image]


== Docker DNS/internet problem ==
<span style="color: red">Note that it is better/necessary to put the Dockerfile in an empty directory</span> to avoid the problem of taking a long time to build the image (''sending build context to Docker daemon ...GB '') since it will grab files from the current directory.
I got an error on resolving the debian server when I was creating an image from a Dockerfile that needs to run ''apt update'' and ''apt install'' commands. See [[#RStudio_in_Docker_.E2.80.93_now_share_your_R_code_effortlessly.21|RStudio in Docker – now share your R code effortlessly!]]. The problem happened on my Linux Mint Desktop but not on a VirtualBox VM (Ubuntu 18.04).


[https://development.robinwinslow.uk/2016/06/23/fix-docker-networking-dns/ Fix Docker's networking DNS config]
<syntaxhighlight lang='bash'>
 
sudo docker search sinatra
A temporary solution is to add the '''--dns''' option to ''docker run'' command. This works well when I use the IP from any one of my 2 DNS servers. It does not work however if I use the IP from google DNS or OpenDNS.
sudo docker pull training/sinatra
sudo docker run -t -i training/sinatra /bin/bash
sudo docker commit -m="Added json gem" -a="Kate Smith" 0b2616b0e5a8 ouruser/sinatra:v2
sudo docker images
 
mkdir sinatra
cd sinatra
touch Dockerfile
sudo docker build -t="ouruser/sinatra:v2" .
sudo docker push ouruser/sinatra
sudo docker rmi training/sinatra
</syntaxhighlight>


A permanent solution is to create a new file '''/etc/docker/daemon.json''' and include the working DNS server IPs (these are obtained through the '''nmcli''' command or the NetworkManager GUI; see [[Linux#Query_DNS_server|Query DNS server]]).
* I get an error when I try to launch sinatra on my 32-bit ubuntu (Docker can only be installed through apt-get on 32-bit)
<pre>
<pre>
{
$ sudo docker run -t -i training/sinatra /bin/bash
    "dns": ["XXX.XX.XX.XX", "YYY.YY.YY.YY"]
2014/12/31 02:43:26 exec format error
}
</pre>
</pre>
Then restart the docker service: '''sudo service docker restart'''


A quick test on the DNS problem is
=== How to copy Docker images from one host to another without using a repository ===
https://stackoverflow.com/questions/23935141/how-to-copy-docker-images-from-one-host-to-another-without-using-a-repository
<syntaxhighlight lang='bash'>
docker save -o out.tar <image name>
# Or better to compress the file
docker save <docker image name> | gzip > out.tar.gz
</syntaxhighlight>
And restore
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker run --rm busybox nslookup google.com
docker load -i out.tar
# Or decompress the file
docker load < out.tar.gz
</syntaxhighlight>
</syntaxhighlight>


== Working with Docker hub ==
=== Docker Image Manifest ===
https://docs.docker.com/userguide/dockerrepos/
[https://www.cloudsavvyit.com/12330/what-is-a-docker-image-manifest/ What Is a Docker Image Manifest?]


== Enabling HTTPS/Let's encrypt ==
=== Resources allocated to a container using docker? ===
* https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion
https://stackoverflow.com/questions/16084741/how-do-i-set-resources-allocated-to-a-container-using-docker
* [https://medium.com/bros/enabling-https-with-lets-encrypt-over-docker-9cad06bdb82b Enabling HTTPS with Let's Encrypt on Docker]
 
* [https://www.humankode.com/ssl/how-to-set-up-free-ssl-certificates-from-lets-encrypt-using-docker-and-nginx How to Set Up Free SSL Certificates from Let's Encrypt using Docker and Nginx] and the [https://github.com/thecarlo/letsencrypt-docker-nginx source code].
== hub.docker.com ==
* [http://www.56n.dk/setup-encrypted-rstudio-and-shiny-dashboard-solution-in-3-minutes/ Setup encrypted Rstudio and Shiny dashboard solution in 3 minutes] (2017). Not working now. ERROR: manifest for mikkelkrogsholm/rstudio:latest not found. After changing to use rocker/rstudio & rocker/shiny images, a new error came out <syntaxhighlight lang='bash'>
* Note that Dockerfile is optional on https://registry.hub.docker.com.
ERROR: for nginx  Cannot start service nginx: b'driver failed programming external connectivity on endpoint
* For free account, we can have only [https://docs.docker.com/docker-hub/repos/ 1 free private repository]. If we want to create a new repository online, we can
nginx (879b01885acd6a0778d9403f4220851e83bd2ff8de643ce91c21cecd25419f83): Error starting userland proxy:
: <syntaxhighlight lang='bash'>
listen tcp 0.0.0.0:443: bind: address already in use'
docker tag local-image:tagname new-repo:tagname
ERROR: Encountered errors while bringing up the project.
docker login
docker push new-repo:tagname
</syntaxhighlight>
* [https://stackoverflow.com/a/28349540 How to push a docker image to a private repository]
* [https://registry.hub.docker.com/repos/rocker/ rocker]. The Dockerfile is included there. Question: how to automatically build the image rather than uploading pre-built image binaries to Docker Hub?
* Search all repositories related to [https://registry.hub.docker.com/search?q=r&searchfield= R]
* [http://phusion.github.io/baseimage-docker/ baseimage-docker]. I can use ping command without special argument when I start phusion/baseimage.
: <syntaxhighlight lang='bash'>
docker pull phusion/baseimage
docker run -ti phusion/baseimage /bin/bash
</syntaxhighlight>
</syntaxhighlight>
* [https://medium.com/bros/enabling-https-with-lets-encrypt-over-docker-9cad06bdb82b Enabling HTTPS with Let's Encrypt on Docker] using Nginx.
* https://dockerfile.github.io/ which includes dockerfiles for different purposes. The ubuntu-desktop one also works well (client needs a vnc viewer in order to see the desktop).


== Enabling HTTPS by self-sign certificates ==
=== Set up a private Docker registry ===
* [https://www.johnmackenzie.co.uk/post/creating-self-signed-ssl-certificates-for-docker-and-nginx/ Creating Self-Signed SSL Certificates For Docker and Nginx]
* https://docs.docker.com/registry/ <syntaxhighlight lang='bash'>
* [https://medium.com/@oliver.zampieri/self-signed-ssl-reverse-proxy-with-docker-dbfc78c05b41 Self-signed SSL Reverse proxy with Docker]
docker run -d -p 5000:5000 --name registry registry:2
* [https://codefresh.io/docker-tutorial/using-docker-generate-ssl-certificates/ Using Docker to Generate SSL Certificates]
docker pull ubuntu
* [https://medium.com/@mannycodes/configure-self-signed-ssl-for-nginx-docker-from-a-scratch-7c2bcd5478c6 Configure Self-Signed SSL For Nginx Docker From A Scratch]
docker image tag ubuntu localhost:5000/myfirstimage
* [https://smithtalkstech.com/2018/04/25/creating-a-self-signed-ssl-certificate-for-local-docker-development/ Creating a self-signed SSL certificate for local Docker development]
docker push localhost:5000/myfirstimage
docker pull localhost:5000/myfirstimage
docker container stop registry && docker container rm -v registry
</syntaxhighlight>
* https://docs.docker.com/registry/deploying/
* [https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-14-04 Ubuntu 14.04] from digitalocean
* [https://www.howtoforge.com/tutorial/how-to-setup-private-docker-registry-on-ubuntu-1804-lts/ How to Setup Private Docker Registry on Ubuntu 18.04 LTS]
* [http://www.thegeekstuff.com/2017/01/secure-docker-registry/ How to Setup Secure Docker Registry on Linux using TLS SSL Certificate]
* List repositories in the local registry. [https://docs.docker.com/registry/spec/api/#listing-image-tags Docker Registry HTTP API V2] and [https://stackoverflow.com/a/14978657 HTTP POST and GET using cURL in Linux].
: <syntaxhighlight lang='bash'>
$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:5000/v2/_catalog
$ OR
$ curl -H "Accept: application/xml" -H "Content-Type: application/json" -X GET http://localhost:5000/v2/_catalog
</syntaxhighlight>
* [https://www.howtogeek.com/devops/how-to-login-to-docker-hub-and-private-registries-with-the-docker-cli/ How to Login to Docker Hub and Private Registries With The Docker CLI]
 
=== Github registry ===
* [https://www.docker.com/blog/docker-support-for-the-new-github-container-registry/ Docker Support for the New GitHub Container Registry]
* [https://docs.github.com/en/packages/guides/migrating-to-github-container-registry-for-docker-images Migrating to GitHub Container Registry for Docker images]
* [https://www.cloudsavvyit.com/6871/how-to-get-started-with-githubs-new-docker-container-registry/ How to Get Started with Github’s New Docker Container Registry]
* [https://nikiforovall.github.io/docker/2020/09/19/publish-package-to-ghcr.html Publish images to GitHub Container Registry (ghcr)]
 
<pre>
docker pull ghcr.io/OWNER/IMAGE_NAME:TAG
 
# docker pull registry-url/image-name:tag
</pre>


== Nginx reverse proxy ==
=== Google Container Registry ===
* [https://dev.to/domysee/setting-up-a-reverse-proxy-with-nginx-and-docker-compose-29jg Setting up a Reverse-Proxy with Nginx and docker-compose]
<ul>
* [https://linoxide.com/containers/setup-nginx-reverse-proxy-docker/ How to Setup NGINX as Reverse Proxy Using Docker]. It works.
<li>Authenticate with Google Cloud: ensure you have the Google Cloud SDK installed
** Download the code from https://github.com/a-magdy/nginx-reverse-proxy-docker.
<pre>
** On the step of modifying /etc/hosts, change the IP address from 172.31.30.78 to 127.0.0.1 for site1.test and site2.test. Or I can use '''docker inspect XXXX | grep IPAddress''' to find out the IP for site1_default and site2_default (these two names are defined in <docker-compose.yml>).
gcloud auth login
** Before creating proxy container, though two web services are up and running inside container, we still cannot test site1.test and site2.test.
gcloud auth configure-docker
** docker-compose build shows successful build. But where is the image?
</pre>
** ''curl site1.test'' and ''curl site2.test'' work fine.
<li>Pull the image
** We can also use a browser to check these two URLs. For https it still works though FF gives warnings for self signed certificates.
<pre>
** '''nmap localhost''' will show ports 80 & 443 are open.
docker pull gcr.io/PROJECT_ID/IMAGE_NAME:TAG
* [https://www.freecodecamp.org/news/docker-nginx-letsencrypt-easy-secure-reverse-proxy-40165ba3aee2/ How to set up an easy and secure reverse proxy with Docker, Nginx]
* [http://littlebigextra.com/install-nginx-reverse-proxy-server-docker/ How to install Nginx as a reverse proxy server with Docker]. Note that http://microservice1:8080;  needs to be changed to reflect the true IP whether it is from a docker container or not. Also it does not work when I modify the --link option to use site1_app_1 and site2_app_1.
{{Pre}}
docker: Error response from daemon: Cannot link to /site1_app_1, as it does not belong to the default network.
</pre>
</pre>
</ul>


== Running multiple web applications on a Docker host ==
=== Google Artifact Registry ===
* https://medium.com/@jmarhee/running-multiple-web-applications-on-a-docker-host-with-apache-85f673f02803. Tips: Enable proxy module in Apache. In the ''VirtualHost'' file, specify '''ProxyPass''' with a port number. No need to specify the DocumentRoot.
https://cloud.google.com/artifact-registry/
* https://medium.com/@francoisromain/host-multiple-websites-with-https-inside-docker-containers-on-a-single-server-18467484ab95. Nginx reverse-proxy is used.
<ul>
* https://blog.florianlopes.io/host-multiple-websites-on-single-host-docker/. [https://github.com/jwilder/nginx-proxy jwilder/nginx-proxy] is used. No need (and should not to avoid a conflict of port 80) to install Nginx <syntaxhighlight lang='bash'>
<li>Authenticate with Google Cloud: ensure you have the Google Cloud SDK installed
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy
<pre>
gcloud auth login
gcloud auth configure-docker us-central1-docker.pkg.dev
</pre>
<li>Pull the image
<pre>
docker pull us-central1-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME:TAG
</pre>
</ul>


sudo nano /etc/hosts # add blog.domain.com and jenkins.domain.com for our testing purpose
== Dockerfile ==
 
* A Dockerfile does not follow the YAML syntax or the shell syntax. It is a plain text file that contains instructions for building a Docker image, using its own specific syntax and keywords.
docker run -d --expose 80 -e VIRTUAL_HOST=blog.domain.com wordpress
* [https://docs.docker.com/reference/builder/ Dockerfile Reference]
docker run -d --name jenkinsci --expose 8080 -e VIRTUAL_HOST=jenkins.domain.com -e VIRTUAL_PORT=8080 jenkins
* [https://www.digitalocean.com/community/tutorials/docker-explained-using-dockerfiles-to-automate-building-of-images Using Dockerfiles to Automate Building of Images] from digitalocean.com.
</syntaxhighlight>
* <strike><span style="color: red">Remember to put the Dockerfile in an empty directory</span></strike>.
** Use VIRTUAL_PORT if there are multiple ports associated with a container
* [https://medium.com/better-programming/what-goes-into-a-dockerfile-ff0ace591060 What goes into a Dockerfile]
** Use VIRTUAL_HOST if there are multiple domains associated with a container
* Keywords
** SSL and et al
** FROM. If we want to start from scratch, we can use ''FROM scratch''.
** RUN. The argument for RUN is any valid Linux command.
** [https://docs.docker.com/engine/reference/builder/#user USER]. This is useful if we want to create new files with a non-root owner privilege. For example, new files created under a binding directory with a non-root user ownership will belong to the current user in the host system. [https://github.com/jlintusaari/R-docker-report.git Here] is an example where we use Rmarkdown to create pdf output. The generated pdf file should not be own by root. [https://stackoverflow.com/a/27703359 How to add users to Docker container?] [https://biolitika.si/pin-r-package-versions-using-docker-and-renv.html Switch users].
** COPY & ADD.
*** "COPY . /app" will copy all files and folders from the current directory recursively to the /app folder. We can use "ADD" too but "ADD" will automatically unpack tarballs. See [https://stackoverflow.com/a/24958548 What is the difference between the `COPY` and `ADD` commands in a Dockerfile?]
*** "ADD sample.tar /app/bin" will unpack the ''sample.tar' file into the target folder
*** "ADD <nowiki>http://example.com/sample.txt</nowiki> /data/" will copy the remote file sample.txt into the target file
** WORKDIR. Define the working directory or context that is used when a container is run from the image.
** CMD & ENTRYPOINT. These two are actually definitions of what will happen when a container is started from the image.
*** Use CMD without ENTRYPOINT: "CMD command param1 param2". This form is called the '''shell''' form.
*** If we use ENTRYPOINT + CMD, ENTRYPOINT defines the command and CMD defines parameters. The example above will run ''ping 8.8.8.8 -c 3''. This form is called the '''exec''' form.
* [https://github.com/jamtur01/dockerbook-code The Docker Book]


== GUI apps ==
=== Examples of Dockerfile ===
* https://github.com/mviereck/x11docker/ which was used by [https://github.com/ehough/docker-kodi Docker-kodi]
* [https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers Only the instructions RUN, COPY, ADD create layers.]
* https://pelle.io/2014/07/11/delivering-gui-applications-with-docker/ Forward X11 approach
* A sample. Six layers (lines). The first line is the Base Layer.
* https://linuxmeerkat.wordpress.com/2014/10/17/running-a-gui-application-in-a-docker-container/ Forward X11
<pre>
* http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ Share X11 socket
FROM python:2.7
* https://github.com/rogaha/docker-desktop  Xpra + Xephyr
RUN mkdir -p /app
* https://github.com/fcwu/docker-ubuntu-vnc-desktop VNC approach
WORKDIR /app
 
COPY ./requirements.txt /app/
== Pruning unused resources ==
RUN pip install -r requirements.txt
* Prune containers
CMD ["python", "main.py"]
<syntaxhighlight lang='bash'>
</pre>
docker container prune # remove all containers that are not in ''running'' status
* Another example
                      # Docker will ask for confirmation before deleting the containers
<pre>
FROM alpine:latest
ENTRYPOINT ["ping"]
CMD ["8.8.8.8", "-c", "3"]
</pre>
* Another example from [https://github.com/rocker-org/rocker/blob/master/r-base/4.0.0/Dockerfile RStudio]
<pre>
FROM debian:testing
RUN useradd docker \
&& mkdir /home/docker \
&& chown docker:docker /home/docker \
&& addgroup docker staff
</pre>
We can test it by "docker build -t mydebian .  " and "docker run --rm -it --user docker -v /tmp:/home/docker mydebian". We can create a new file under /home/docker and the file will be accessible and belongs to the current host user once we quit the container. '''This actually is a huge security issue'''.
 
The same technique does not work on alpine if I try to create a new file in the container.
<pre>
FROM alpine:latest
# Create a group and user; not useful for creating files in host OS
RUN addgroup -S appgroup && adduser -S appuser -G appgroup \
          && chown appuser:appgroup /home/appuser
</pre>
"docker build -t myalpine . " and "docker run --rm -it -v ~/Downloads/:/home/appuser:rw --user appuser myalpine". When I use the "id" command in the container, I see it returns 100 in alpine container and 1000 in debian container.  The id returns 1000 on my host (Ubuntu/Pop_OS). So the solution is '''docker run --rm -it -v ~/Downloads/:/home/appuser --user 1000:1000 myalpine'''. So the local user and the created user home directory in the container are not needed. See
<ul>
<ul>
<li> [https://jtreminio.com/blog/running-docker-containers-as-current-host-user/ Running Docker Containers as Current Host User] (Useful !)</li>
<li> [https://stackoverflow.com/a/45673309 How to give non-root user in Docker container access to a volume mounted on the host] </li>
</ul></ul>
 
==== Rocker ====
* [https://github.com/rocker-org/rocker rocker (R and RStudio)]
* [https://github.com/hrbrmstr/rdaradar rdaradar (RDA Radar)]
<pre>
FROM r-base:latest
COPY check.R .
CMD [ "Rscript", "check.R", "/unsafe.rda"]
</pre>
<pre>
$ git clone https://github.com/hrbrmstr/rdaradar.git
$ docker build -t rdaradar:0.1.0 -t rdaradar:latest . 
$ docker run --rm -v "$(pwd)/exploit.rda:/unsafe.rda" rdaradar
</pre>
 
==== Bioconductor ====
[https://github.com/Bioconductor/bioconductor_docker Bioconductor]
 
==== Papers ====
* [https://github.com/amyfrancis97/DrivR-Base DrivR-Base], [https://f1000research.com/posters/12-1521 Poster], [https://academic.oup.com/bioinformatics/article/40/4/btae197/7644281 Paper] 2024
 
=== How to use Dockerfile ===
https://docs.docker.com/engine/reference/commandline/build/


docker container prune -f
[https://stackoverflow.com/a/55034787 The . simply means "current working directory"].
docker container rm -f $(docker container ls -aq) # remove even the running containers
</syntaxhighlight>
* Prune images
<syntaxhighlight lang='bash'>
docker images prune # unused image layers
</syntaxhighlight>
* Prune volumes
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker volume prune # unused volumes by at least one container
docker build -f Dockerfile -t arraytools/myimagename .


docker volume prune --filter 'label=demo'
docker build -t [myname] . 
docker volume prune --filter 'label=demo' --filter 'label=test'
# Multiple tags
docker build -t arraytools/biospear:latest -t arraytools/biospear:3.6.0 .
</syntaxhighlight>
</syntaxhighlight>
* Prune networks
 
In the above example, we can create the image by
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker network prune
docker image build -t pinger .
</syntaxhighlight>
</syntaxhighlight>
* Prune everything
We can run a container from the pinger image
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker system prune
docker container run --rm -it pinger
</syntaxhighlight>
</syntaxhighlight>


== Misc ==
=== Docker Build Args ===
=== LXC (raw Linux containers) ===
[https://www.howtogeek.com/devops/how-to-use-docker-build-args-to-configure-image-builds/ How to Use Docker Build Args to Configure Image Builds]
* https://help.ubuntu.com/lts/serverguide/lxc.html
 
* https://help.ubuntu.com/community/LXC
=== "docker buildx build" vs "docker build" ===
* https://askubuntu.com/questions/293275/what-is-lxc-and-how-to-get-started
* '''docker build''' is essentially a wrapper or alias for '''docker buildx build''', but it always uses the default builder for backwards compatibility
* [https://www.cyberciti.biz/faq/how-to-install-lxd-container-hypervisor-on-ubuntu-16-04-lts-server/ Setup Linux Container with LXC on Ubuntu 16.04]
* Difference between docker build and docker buildx build - [https://docs.docker.com/build/builders/ Docker builder] documentation, [https://github.com/docker/buildx github] page.
* [http://en.community.dell.com/techcenter/os-applications/w/wiki/6950.lxc-containers-in-ubuntu-server-14-04-lts LXC containers in Ubuntu Server 14.04 LTS]
* An example [https://fragpipe-analyst-doc.nesvilab.org/documentation/installation.html FlagPipe Analyst]
* [https://blog.simos.info/trying-out-lxd-containers-on-our-ubuntu/ Trying out LXD containers on our Ubuntu]
** Multi-platform Support (--platform)
** Output Option (--output=type=docker)


==== LXC vs Docker ====
=== Clean up after failed builds ===
* https://diveintodocker.com/blog/why-i-got-started-with-docker
[https://gist.github.com/kuznero/0c751283ea77177a1db9 Cleanup docker images and containers after failed builds]
* https://unix.stackexchange.com/questions/254956/what-is-the-difference-between-docker-lxd-and-lxc and https://i.stack.imgur.com/a5Neb.png
<pre>
#!/bin/bash
docker rm $(docker ps -aq) \
  docker rmi $(docker images | grep "^<none>" | awk '{print $3}')
</pre>


=== Vagrant vs Docker ===
=== ENTRYPOINT and CMD ===
* http://stackoverflow.com/questions/16647069/should-i-use-vagrant-or-docker-io-for-creating-an-isolated-environment
* If your container acts like a command-line program, you can use '''ENTRYPOINT'''. If you are unsure, you can use '''CMD'''.
* https://deliciousbrains.com/vagrant-docker-wordpress-development/
* [https://blog.codeship.com/understanding-dockers-cmd-and-entrypoint-instructions/ Understanding Docker’s CMD and ENTRYPOINT Instructions]. It shows how to supply arguments to the command we like to execute in the container.
** Vagrant is easier to understand and is easier to get up and running but can be very resource intensive (in terms of RAM and space).
* https://docs.docker.com/engine/reference/builder/#cmd
** Docker’s architecture is harder to understand and can be harder to get up and running but is much faster, uses much less CPU and RAM and potentially uses much less space than Vagrant VM’s.
** [https://dille.name/blog/2019/12/05/creating-advanced-entrypoints-for-containers/ Creating Advanced Entrypoints for Containers]. In this case CMD provides extra parameters to ENTRYPOINT.
* https://youtu.be/9QGkJvbLpRA?t=3m22s
** The Dockerfile from [https://jlintusaari.github.io/2018/07/how-to-compile-rmarkdown-documents-using-docker/ How to compile R Markdown documents using Docker] uses both ENTRYPOINT and CMD where in this case CMD provides extra parameters to ENTRYPOINT.
** Docker uses container technology while vagrant uses virtual machines.
** If security is a concern, use vagrant and virtual machine
** For speeding development and sharing, use Docker.
** Most teams use both to run a smooth operation


=== Date/Time zone ===
'''The advantage of using ENTRYPOINT + CMD''' (exec form) instead of using '''CMD''' alone (shell form) is we can override the ''CMD'' part that I have defined in the Dockerfile.
* http://tedwise.com/2015/05/02/setting-the-timezone-in-a-docker-image/
* https://stackoverflow.com/questions/22800624/will-docker-container-auto-sync-time-with-the-host-machine
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker run --rm -t -i -v /etc/localtime:/etc/localtime:ro ubuntu date
docker container run --rm -it pinger -w 5 127.0.0.1
# ping the loopback for 5 seconds
</syntaxhighlight>
</syntaxhighlight>
* https://serverfault.com/questions/683605/docker-container-time-timezone-will-not-reflect-changes


=== Access the internet from the container ===
If we want to overwrite what's defined in the ''ENTRYPOINT'' in the Dockerfile, we need to use the ''--entrypoint'' parameter.
Run the container with the '--net=host' option
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
sudo docker run --net=host -it ubuntu /bin/bash
docker container run --rm -it --entrypoint /bin/sh pinger
# we'll be inside the container. Type exit to leave the container
</syntaxhighlight>
</syntaxhighlight>


=== How to transfer/copy an image to another host ===
When we use the '''shell''' form, the '''ENTRYPOINT''' is have the default value of ''/bin/sh -c'' and whatever is the value of ''CMD'' will be passed as a string to the shell command.
[https://stackoverflow.com/a/23938978 How to copy Docker images from one host to another without using a repository]
<syntaxhighlight lang='bash'>
# Step 1: save the Docker image as a tar file:
docker save -o <path for generated tar file> <image name>


# Step 2: copy your image to a new system with regular file transfer tools such as cp or scp.  
=== Temporary failure resolving 'deb.debian.org' when running "docker build" ===
Add "--net=host" to the docker build command. See [https://stackoverflow.com/questions/24991136/docker-build-could-not-resolve-archive-ubuntu-com-apt-get-fails-to-install-a Docker build “Could not resolve 'archive.ubuntu.com'” apt-get fails to install anything]


# Step 3: After that you will have to load the image into Docker:
=== Best practices for writing Dockerfiles ===
docker load -i <path to image tar file>
* https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
</syntaxhighlight>
* [https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices/ Intro Guide to Dockerfile Best Practices]
The tar file size is the same as what we get from 'docker image'. If we use the 'gzip' utility, it can reduce the file size (e.g 2.7GB to 1.1GB).


Or https://stackoverflow.com/a/39716019
=== Use multi-stage builds ===
<syntaxhighlight lang='bash'>
* https://docs.docker.com/develop/develop-images/multistage-build/
# Step 1:
* [https://www.cloudsavvyit.com/9260/what-are-multi-stage-docker-builds/ What Are Multi-Stage Docker Builds?]
docker save docker-image-name | gzip > my-image.tar.gz
# Step 3:
docker load < my-image.tar.gz
</syntaxhighlight>


=== Where are Docker images stored on the host: /var/lib/docker ===
With multi-stage builds, we have a single Dockerfile containing multiple FROM instructions. Each FROM instruction is a new '''build stage''' that can easily COPY artifacts from previous '''stages'''.
* http://blog.thoward37.me/articles/where-are-docker-images-stored/
* http://stackoverflow.com/questions/19234831/where-are-docker-images-stored-on-the-host-machine
* https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-storage-driver
* http://stackoverflow.com/questions/21016210/function-of-docker-directory-structure-in-var-lib-docker


The default is '''/var/lib/docker'''. The location can be changed by modifying the file '''/etc/default/docker'''. Three options if we are tight on the disk space.
[https://github.com/nigelpoulton/atsea-sample-shop-app An example] from the "Docker Deep Dive" book.


'''1. Create a softlinks''' for the Docker data directory (/var/lib/docker) and for /var/lib/docker/tmp as described at [https://docs.docker.com/engine/reference/commandline/dockerd/#miscellaneous-options miscellaneous-options]. See [https://stackoverflow.com/a/40919928 this]. See [https://stackoverflow.com/a/40192707 for how to stop docker daemon] on different OS.
=== tag after image was built ===
<syntaxhighlight lang='bash'>
<pre>
sudo service docker stop  # or sudo systemctl stop docker
$ docker tag <imageID> <newName>/<repoName>:<tagName>
sudo mv /var/lib/docker /a/new/location
</pre>
sudo ln -s /a/new/location /var/lib/docker # Create a symbolic link
sudo service docker start  # or sudo systemctl start docker
</syntaxhighlight>


'''2. Change the default location to another place'''. For example,
=== About storage drivers ===
<syntaxhighlight lang='bash'>
https://docs.docker.com/storage/storagedriver/#sharing-promotes-smaller-images
sudo nano /etc/default/docker
# Add a line DOCKER_OPTS="-g /home/brb/Docker"
</syntaxhighlight>
Then after running ''sudo service docker.io restart'' and then a simple pull '''sudo docker pull rocker/r-base''' or '''sudo docker run --rm -ti rocker/r-base''' (the Dockerfile of r-base is available on [https://github.com/rocker-org/rocker/blob/master/r-base/Dockerfile github.com], '''--rm''' option means Automatically remove the container when it exits), we will see something like this:
<syntaxhighlight lang='bash'>
$ docker run --rm -ti rocker/r-base
$ docker images
$ docker -v
Docker version 1.0.1, build 990021a
 
$ docker -D info | grep Root
Root Dir: /home/brb/Docker/aufs
</syntaxhighlight>


=== Consuming Docker system events ===
=== Privileged versus Root user in Docker ===
<syntaxhighlight lang='bash'>
* [https://www.cloudsavvyit.com/5211/privileged-vs-root-in-docker-whats-the-difference/ Privileged versus Root in Docker: What’s the Difference?]
# Open a new terminal
* [https://itnext.io/docker-and-kubernetes-root-vs-privileged-9d2a37453dec Docker and Kubernetes — root vs. privileged]
docker system events
# This command is a blocking command.  
# Thus, when you execute it in your terminal session the according session is blocked.


# Open another terminal
=== .dockerignore ===
docker container run --rm alpine echo "Hello World"
[https://devopsheaven.com/docker/dockerignore/2018/04/25/using-dockerignore.html Using .dockerignore files to build better Docker images]
</syntaxhighlight>


=== Monitor tools ===
=== Dockerfile in One Line ===
* [https://www.2daygeek.com/ctop-a-command-line-tool-for-container-monitoring-and-management-in-linux/# cTop – A Command-Line Tool For Container Monitoring And Management In Linux], [https://github.com/bcicen/ctop ctop]
<pre>
FROM ubuntu
</pre>
Using This simple Dockerfile and the docker command '''sudo docker build -t scooby_snacks .''' will result in
<pre>
$ sudo docker images
REPOSITORY          TAG                IMAGE ID            CREATED            VIRTUAL SIZE
ubuntu              15.04              2427658c75a1        42 hours ago        117.5 MB
ubuntu              vivid              2427658c75a1        42 hours ago        117.5 MB
ubuntu              vivid-20150218      2427658c75a1        42 hours ago        117.5 MB
ubuntu              utopic-20150211    78949b1e1cfd        42 hours ago        194.4 MB
ubuntu              utopic              78949b1e1cfd        42 hours ago        194.4 MB
ubuntu              14.10              78949b1e1cfd        42 hours ago        194.4 MB
ubuntu              14.04              2d24f826cb16        42 hours ago        188.3 MB
ubuntu              14.04.2            2d24f826cb16        42 hours ago        188.3 MB
ubuntu              trusty              2d24f826cb16        42 hours ago        188.3 MB
ubuntu              trusty-20150218.1  2d24f826cb16        42 hours ago        188.3 MB
ubuntu              latest              2d24f826cb16        42 hours ago        188.3 MB
scooby_snacks      latest              2d24f826cb16        42 hours ago        188.3 MB
ubuntu              precise            1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              precise-20150212    1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              12.04.5            1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              12.04              1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              14.04.1            5ba9dab47459        3 weeks ago        188.3 MB
ubuntu              12.10              c5881f11ded9        8 months ago        172.2 MB
ubuntu              quantal            c5881f11ded9        8 months ago        172.2 MB
ubuntu              13.04              463ff6be4238        8 months ago        169.4 MB
ubuntu              raring              463ff6be4238        8 months ago        169.4 MB
ubuntu              13.10              195eb90b5349        8 months ago        184.7 MB
ubuntu              saucy              195eb90b5349        8 months ago        184.7 MB
ubuntu              10.04              3db9c44f4520        10 months ago      183 MB
ubuntu              lucid              3db9c44f4520        10 months ago      183 MB
</pre>


== [https://docs.docker.com/machine/overview/ Docker Machine] ==
== List all tags of an image ==
Docker Machine is a tool that lets you
[https://stackoverflow.com/a/39454426 How can I list all tags for a Docker image on a remote registry?]
* Install Docker Engine on virtual hosts. You can use Machine (a unified way) to create Docker hosts on your local Mac or Windows box, on your company network, in your data center, or on cloud providers like Azure, AWS, or Digital Ocean. See the comment on [https://sreeninet.wordpress.com/2015/05/31/docker-machine/ here].
* Provision and manage multiple remote Docker hosts
* Provision Swarm clusters


Docker machine is not installed in Linux when you install Docker. See the instruction on [https://docs.docker.com/machine/install-machine/ here] to install it.
=== Tag the image with the git commit ID ===
 
My feeling is if we just want to play Docker on a local Linux machine, we don't really need to use Docker Machine (it just make life more complicated). But if we are working on Mac/Windows or we want to work on clouds or test on VirtualBox, we shall use Docker machines.
 
[https://youtu.be/OWhhOQAiGt0 Use Docker-machine to Create Docker Servers]. Compare the Docker images on the local machine (server 1) & a new host (server 2) created by '''docker-machine'''. Question: 1. how to tell we are in the host/machine environment? 2. how to exit the host environment after we use ''eval $() command? docker-machine stop MachineName.
<pre>
<pre>
$ docker-machine help
$ docker build -t REPOS/IMAGE:$(git rev-parse --verify HEAD)
$ docker-machine create --driver=virtualbox test
# Follow its hint on the output, issue the following command
$ docker-machine env test
# Follow its hint on the output, issue the following command
$ eval$(docker-machine env test) # will configure the docker CLI to connect to this docker machine 'test'
                                # This is equivalent to running 4 export commands on the command line
$ docker-machine ls  # Very useful
$ docker-machine stop test
$ docker-machine ip test
$ docker-machine start test
$ docker-machine rm test
</pre>
</pre>


[https://youtu.be/rnaLmSkZfKk Play Docker Machine on Mac with Virtualbox]. Docker can be used to create a virtual machine just like Vagrant.
== Run a shell script on host ==
<pre>
* https://docs.docker.com/engine/reference/commandline/run/
$ docker-machine create -d virtualbox demo
* [https://serverfault.com/questions/806812/docker-run-bash-script-then-remove-container This post] and [https://stackoverflow.com/questions/32163955/how-to-run-shell-script-on-host-from-docker-container this one]
$ docker-machine ls
<pre style="white-space: pre-wrap; /* CSS 3 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* IE 5.5+ */ " >
$ docker run -v /path/to/sample_script.sh:/sample_script.sh \
  --rm ubuntu bash sample_script.sh


# first way to access a Docker host
# GATK container example
$ docker-machine ssh demo
# First we log in interactive and see where is the default location (/usr in this case)
docker@demo:~$ docker images # empty for now
$ docker run --rm -i -t broadinstitute/gatk3:3.8-0 bash
 
$ cat > tmp.sh << EOF
# second way to access
> pwd
$ docker-machine env demo
> ls
$ eval $(docker-machine env demo)
> java -jar GenomeAnalysisTK.jar --version
$ docker version
> EOF
$ docker run --rm -v $(pwd):/usr/my broadinstitute/gatk3:3.8-0 bash my/tmp.sh
# ALTERNATIVELY, WE CAN PUT OUR SCRIPT IN THE TOP DIRECTORY (Hopefully the name is not duplicated)
$ docker run --rm -v $(pwd)/tmp.sh:/tmp.sh broadinstitute/gatk3:3.8-0 bash /tmp.sh
</pre>
</pre>
 
* https://askubuntu.com/questions/890533/how-can-i-run-docker-commands-after-docker-run-from-a-script (need to leave a container open)
[http://rancher.com/rancher-os/ RancherOS demo video] used the '''docker-machine''' command to pull and run the RancherOS.
<pre>
<pre>
docker-machine create -d virtualbox --virtualbox-boot2docker-url https://releases.rancher.com/os/latest/rancheros.iso demo
docker run -d -v$(pwd):/my SOMEIMAGE bash
docker-machine ssh demo
docker exec -d Test bash /my/script.sh
ps
docker ps
sudo system-docker ps
 
sudo ros help
sudo ros console list
sudo ros console switch ubunu
apt-get help
</pre>
</pre>
* Create a Dockerfile https://forums.docker.com/t/how-to-run-bash-command-after-startup/21631/2


== Docker Compose <docker-compose.yaml> ==
== Link containers together ==
Docker Compose can help us out as it allows us to specify a single file in which we can define our entire environment structure and run it with a single command (much like a Vagrantfile works).  
* https://docs.docker.com/userguide/dockerlinks/
* [https://hub.docker.com/r/simplyintricate/mediawiki/ Mediawiki example]


* https://docs.docker.com/compose/ (the example will give an error when "RUN pip install -r requirements.txt")
== Manage data in containers ==
*# app.py
* https://docs.docker.com/storage/volumes/
*# requirements.txt
* https://codereviewvideos.com/course/docker-tutorial-for-beginners/video/part-2-docker-volumes-volumes
*# Dockerfile
*# docker-compose.yml
* Some top-level '''keys''': version, services, networks, volumes
* [https://stackoverflow.com/questions/38507446/docker-dockerfile-vs-docker-compose-yml Dockerfile vs docker-compose.yml]
* A simple example of running [https://www.tutorialspoint.com/docker/docker_compose.htm nginx & mysqsl]
* [https://youtu.be/Qw9zlE3t8Ko Docker Compose in 12 Minutes]
* https://deliciousbrains.com/vagrant-docker-wordpress-development/
* https://github.com/kristophjunge/docker-mediawiki
* [https://www.howtoforge.com/tutorial/docker-guide-dockerizing-python-django-application/ Docker Guide: Dockerizing Python Django Application] (cannot follow)
* Examples:
** [https://github.com/haroldtreen/epub-press EpubPress] local server
** Running [https://github.com/nextcloud/docker nextcloud], [https://blog.ouseful.info/2017/06/16/rolling-your-own-jupyter-and-rstudio-data-analysis-environment-around-apache-drill-using-docker-compose/ Jupyter and RStudio]
** [https://github.com/dceoy/docker-rstudio-server Rstudio]


=== An example from 'Fundamentals of Docker' ===
== Assign a static IP to a container ==
<syntaxhighlight lang='bash'>
* [https://www.cloudsavvyit.com/14508/how-to-assign-a-static-ip-to-a-docker-container/ How to Assign a Static IP to a Docker Container]
git clone https://github.com/fundamentalsofdocker/labs.git
* https://stackoverflow.com/questions/27937185/assign-static-ip-to-docker-container <syntaxhighlight lang='bash'>
cd labs/ch08
# Step 1. create you own docker network (mynet123)
docker-compose up
docker network create --subnet=172.18.0.0/16 mynet123
# Open http://localhost:3000/pet
# Step 2. simply run the image (I'll take ubuntu as example)
</syntaxhighlight>
docker run --rm --net mynet123 --ip 172.18.0.22 -it ubuntu bash
The images do not show up:( The terminal shows what has happened under the hood. So the problem is the http links for images do not exist.
# Check in the container shell
 
# Note that the container CAN access internet
We can also run the application in the background
apt install net-tools; ifconfig
<syntaxhighlight lang='bash'>
exit
docker-compose up -d
</syntaxhighlight>
</syntaxhighlight>
* https://docs.docker.com/engine/reference/commandline/network_create/#bridge-driver-options
* [https://stackoverflow.com/questions/25529386/how-can-i-set-a-static-ip-address-in-a-docker-container Try using the --net=host option] (no a new IP was allocated; not a good solution)


To stop and clean up the application,
== Running Multiple Docker Services on the Same Server ==
<syntaxhighlight lang='bash'>
[https://www.howtogeek.com/devops/how-to-run-multiple-docker-containers-on-different-ip-addresses/ How to Run Multiple Docker Containers on Different IP Addresses]
docker-compose down
</syntaxhighlight>


If we also want to remove the volume for the database
== Firewall ==
<syntaxhighlight lang='bash'>
[https://community.rstudio.com/t/rstudio-server-not-loading-taking-too-long-to-respond-in-browser/20786 Rstudio server not loading, taking too long to respond in browser]. On Ubuntu run ''sudo ufw allow PORTNUMBER''.
docker volume rm ch08_pets-data
</syntaxhighlight>


=== An example from "How to Setup NGINX as Reverse Proxy Using Docker" ===
== Docker DNS/internet problem in 'docker build' or 'docker run' ==
See [[#Nginx_reverse_proxy|here]]. Only nginx is used.
I got an error on resolving the debian server when I was creating an image from a Dockerfile that needs to run ''apt update'' and ''apt install'' commands. See [[#RStudio_in_Docker_.E2.80.93_now_share_your_R_code_effortlessly.21|RStudio in Docker – now share your R code effortlessly!]]. The problem happened on my Linux Mint Desktop but not on a VirtualBox VM (Ubuntu 18.04).


=== An example from "Docker Deep Dive" (flask + redis) ===
[https://development.robinwinslow.uk/2016/06/23/fix-docker-networking-dns/ Fix Docker's networking DNS config]
'''Note''' that on [https://docs.docker.com/compose/gettingstarted/#step-7-update-the-application Get started with Docker Compose] it mounts the current directory to ''/code'' inside the container. So after we modify ''app.py'', we don't need to copy it to the container.


Another one [https://takacsmark.com/docker-compose-tutorial-beginners-by-example-basics/ Docker compose tutorial for beginners by example]
A temporary solution is to add the '''--network=host''' option to ''docker build'' or ''docker run'' command.  
<syntaxhighlight lang='bash'>
$ git clone https://github.com/nigelpoulton/counter-app.git
$ cd counter-app
$ ls
app.py  docker-compose.yml  Dockerfile  README.md  requirements.txt


$ cat requirements.txt
A permanent solution is to create a new file '''/etc/docker/daemon.json''' and include the working DNS server IPs (these are obtained through the '''nmcli''' command or the NetworkManager GUI; see [[Linux#Query_DNS_server|Query DNS server]]).
flask
<pre>
{
  "dns": ["8.8.8.8", "8.8.4.4"]
}
</pre>
Then restart the docker service: '''sudo service docker restart''' or '''sudo systemctl restart docker'''
 
A quick test on the DNS problem is
<syntaxhighlight lang='bash'>
docker run --rm busybox nslookup google.com
</syntaxhighlight>
 
== Working with Docker hub ==
https://docs.docker.com/userguide/dockerrepos/


$ cat Dockerfile
=== Github Actions ===
FROM python:3.4-alpine
* [https://docs.github.com/en/actions/language-and-framework-guides/github-actions-for-docker GitHub Actions for Docker]
ADD . /code
* [https://docs.github.com/en/actions/language-and-framework-guides/publishing-docker-images Publishing Docker images]
WORKDIR /code
* See my [[Github#Github_Actions_.28GHA.29|Github]] page.
RUN pip install -r requirements.txt
CMD ["python", "app.py"]


$ cat docker-compose.yml
== Enabling HTTPS/Let's encrypt ==
version: "3.5"
* [https://caddyserver.com/ Caddy]
services:
* https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion
  web-fe:
* [https://medium.com/bros/enabling-https-with-lets-encrypt-over-docker-9cad06bdb82b Enabling HTTPS with Let's Encrypt on Docker]
    build: .
* [https://www.humankode.com/ssl/how-to-set-up-free-ssl-certificates-from-lets-encrypt-using-docker-and-nginx How to Set Up Free SSL Certificates from Let's Encrypt using Docker and Nginx] and the [https://github.com/thecarlo/letsencrypt-docker-nginx source code].
    command: python app.py
* [http://www.56n.dk/setup-encrypted-rstudio-and-shiny-dashboard-solution-in-3-minutes/ Setup encrypted Rstudio and Shiny dashboard solution in 3 minutes] (2017). Not working now. ERROR: manifest for mikkelkrogsholm/rstudio:latest not found. After changing to use rocker/rstudio & rocker/shiny images, a new error came out <syntaxhighlight lang='bash'>
    ports:
ERROR: for nginx  Cannot start service nginx: b'driver failed programming external connectivity on endpoint
      - target: 5000
nginx (879b01885acd6a0778d9403f4220851e83bd2ff8de643ce91c21cecd25419f83): Error starting userland proxy:  
        published: 5000
listen tcp 0.0.0.0:443: bind: address already in use'
    networks:
ERROR: Encountered errors while bringing up the project.
      - counter-net
</syntaxhighlight>
    volumes:
* [https://medium.com/bros/enabling-https-with-lets-encrypt-over-docker-9cad06bdb82b Enabling HTTPS with Let's Encrypt on Docker] using Nginx.
      - type: volume
        source: counter-vol
        target: /code
  redis:
    image: "redis:alpine"
    networks:
      counter-net:


networks:
== Enabling HTTPS by self-sign certificates ==
  counter-net:
* [https://www.johnmackenzie.co.uk/post/creating-self-signed-ssl-certificates-for-docker-and-nginx/ Creating Self-Signed SSL Certificates For Docker and Nginx]
* [https://medium.com/@oliver.zampieri/self-signed-ssl-reverse-proxy-with-docker-dbfc78c05b41 Self-signed SSL Reverse proxy with Docker]
* [https://codefresh.io/docker-tutorial/using-docker-generate-ssl-certificates/ Using Docker to Generate SSL Certificates]
* [https://medium.com/@mannycodes/configure-self-signed-ssl-for-nginx-docker-from-a-scratch-7c2bcd5478c6 Configure Self-Signed SSL For Nginx Docker From A Scratch]
* [https://smithtalkstech.com/2018/04/25/creating-a-self-signed-ssl-certificate-for-local-docker-development/ Creating a self-signed SSL certificate for local Docker development]


volumes:
== traefik: The Cloud Native Application Proxy ==
  counter-vol:
* https://traefik.io/traefik/
* [https://www.digitalocean.com/community/tutorials/how-to-use-traefik-as-a-reverse-proxy-for-docker-containers-on-ubuntu-18-04 How To Use Traefik as a Reverse Proxy for Docker Containers on Ubuntu 18.04]
* [https://www.howtoforge.com/how-to-install-and-use-traefik-as-a-reverse-proxy-with-docker-on-centos-8/ How to Install and Use Traefik as a Reverse Proxy with Docker on CentOS 8]
* [https://www.digitalocean.com/community/tutorials/how-to-use-traefik-v2-as-a-reverse-proxy-for-docker-containers-on-ubuntu-20-04 How To Use Traefik v2 as a Reverse Proxy for Docker Containers on Ubuntu 20.04]
* [https://medium.com/accesto/docker-reverse-proxy-using-traefik-2657c0086a3d Docker reverse proxy using Traefik]
* [https://blog.eleven-labs.com/en/using-traefik-as-a-reverse-proxy/ USING TRAEFIK AS A REVERSE PROXY]
* [https://youtu.be/N5EmluXSbEg How to Install Traefik 2 on OMV and Docker] DB Tech 2020. Cloudflare, Portainer. Airsonic.
* [https://youtu.be/liV3c9m_OX8 Put Wildcard Certificates and SSL on EVERYTHING - Traefik Tutorial] Apr 2021
* Raspberry Pi
** [https://www.alexhyett.com/traefik-vs-nginx-docker-raspberry-pi Traefik vs Nginx for Reverse Proxy with Docker on a Raspberry Pi]
** [https://codecaptured.com/blog/self-hosting-pi-hole-with-docker-and-traefik/ Self-Hosting Pi-hole with Docker and Traefik]
** [https://blog.pankajgarg.com/helloaspnetcoreonpi/ Running ASP.NET core web application on Raspberry Pi]
* [https://youtu.be/liV3c9m_OX8 Put Wildcard Certificates and SSL on EVERYTHING - Traefik Tutorial] (video)


$ docker-compose up &
== Nginx proxy manager ==
 
* https://nginxproxymanager.com/
$ docker container ls
* [https://www.the-digital-life.com/nginx-proxy-manager/ NGINX Proxy Manager – How-To Installation and Configuration]
* [https://youtu.be/CSbgLBcIuwE Access your internal websites! Nginx Reverse Proxy in Home Assistant]
* [https://www.howtoforge.com/how-to-install-and-use-nginx-proxy-manager/ How to Install and Use Nginx Proxy Manager with Docker] 2022
* [https://www.the-digital-life.com/nginx-proxy-manager/ NGINX Proxy Manager – How-To Installation and Configuration] the-digital-life
* https://hub.docker.com/r/jlesage/nginx-proxy-manager, [https://github.com/jlesage/docker-nginx-proxy-manager Github]
* [https://dev.to/domysee/setting-up-a-reverse-proxy-with-nginx-and-docker-compose-29jg Setting up a Reverse-Proxy with Nginx and docker-compose]
* [https://linoxide.com/containers/setup-nginx-reverse-proxy-docker/ How to Setup NGINX as Reverse Proxy Using Docker]. It works.
** Download the code from https://github.com/a-magdy/nginx-reverse-proxy-docker.
** On the step of modifying /etc/hosts, change the IP address from 172.31.30.78 to 127.0.0.1 for site1.test and site2.test. Or I can use '''docker inspect XXXX | grep IPAddress''' to find out the IP for site1_default and site2_default (these two names are defined in <docker-compose.yml>).
** Before creating proxy container, though two web services are up and running inside container, we still cannot test site1.test and site2.test.
** docker-compose build shows successful build. But where is the image?
** ''curl site1.test'' and ''curl site2.test'' work fine.
** We can also use a browser to check these two URLs. For https it still works though FF gives warnings for self signed certificates.
** '''nmap localhost''' will show ports 80 & 443 are open.
* [https://www.freecodecamp.org/news/docker-nginx-letsencrypt-easy-secure-reverse-proxy-40165ba3aee2/ How to set up an easy and secure reverse proxy with Docker, Nginx]
* [http://littlebigextra.com/install-nginx-reverse-proxy-server-docker/ How to install Nginx as a reverse proxy server with Docker]. Note that http://microservice1:8080;  needs to be changed to reflect the true IP whether it is from a docker container or not. Also it does not work when I modify the --link option to use site1_app_1 and site2_app_1.
{{Pre}}
docker: Error response from daemon: Cannot link to /site1_app_1, as it does not belong to the default network.
</pre>
* [https://phoenixnap.com/kb/docker-nginx-reverse-proxy How to Deploy NGINX Reverse Proxy on Docker] (multiple web services)
* [https://www.howtoforge.com/how-to-install-and-use-portainer-for-docker-management-with-nginx-proxy-manager/ How to Install and Use Portainer for Docker management with Nginx Proxy Manager]
* [https://www.howtogeek.com/how-to-host-your-own-website-with-docker-and-nginx-proxy-manager/ How to Host Your Own Website with Docker and Nginx Proxy Manager] 2025


$ docker network ls
== Running multiple web applications on a Docker host ==
NETWORK ID          NAME                    DRIVER              SCOPE
* https://medium.com/@jmarhee/running-multiple-web-applications-on-a-docker-host-with-apache-85f673f02803. Tips: Enable proxy module in Apache. In the ''VirtualHost'' file, specify '''ProxyPass''' with a port number. No need to specify the DocumentRoot.
2acef6dabde6        bridge                  bridge              local
* https://medium.com/@francoisromain/host-multiple-websites-with-https-inside-docker-containers-on-a-single-server-18467484ab95. Nginx reverse-proxy is used.
a2d42bc482ff        counterapp_counter-net  bridge              local
* https://blog.florianlopes.io/host-multiple-websites-on-single-host-docker/. [https://github.com/jwilder/nginx-proxy jwilder/nginx-proxy] is used. No need (and should not to avoid a conflict of port 80) to install Nginx <syntaxhighlight lang='bash'>
e1e093b64282        host                     host               local
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy
7ecd0a6a9ebd        none                    null                local


# Open the browser http://localhost:5000
sudo nano /etc/hosts # add blog.domain.com and jenkins.domain.com for our testing purpose
$ docker-compose ps
      Name                      Command              State          Ports       
-------------------------------------------------------------------------------------
counterapp_redis_1    docker-entrypoint.sh redis ...  Up      6379/tcp             
counterapp_web-fe_1  python app.py                    Up      0.0.0.0:5000->5000/tcp


$ docker-compose stop
docker run -d --expose 80 -e VIRTUAL_HOST=blog.domain.com wordpress
$ docker-compose ps
docker run -d --name jenkinsci --expose 8080 -e VIRTUAL_HOST=jenkins.domain.com -e VIRTUAL_PORT=8080 jenkins
# We can see stopping a Compose app does not delete the application
</syntaxhighlight>
** Use VIRTUAL_PORT if there are multiple ports associated with a container
** Use VIRTUAL_HOST if there are multiple domains associated with a container
** SSL and et al


$ docker container ls -a
== GUI apps ==
$ docker-compose rm    # delete a stopped Compose app
* [https://www.cloudsavvyit.com/10520/how-to-run-gui-applications-in-a-docker-container/ How to Run GUI Applications in a Docker Container]
                        # images, volumes and source code remain
* https://github.com/mviereck/x11docker/ which was used by [https://github.com/ehough/docker-kodi Docker-kodi]
$ docker-compose restart
* https://pelle.io/2014/07/11/delivering-gui-applications-with-docker/ Forward X11 approach
                        # If you made changes to your Compose app since stopping,
* https://linuxmeerkat.wordpress.com/2014/10/17/running-a-gui-application-in-a-docker-container/ Forward X11
                        # these changes will not appear in the restarted app.
* http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ Share X11 socket
                        # You need to re-deploy the app to get the changes.
* https://github.com/rogaha/docker-desktop  Xpra + Xephyr
$ docker-compose ps
* https://github.com/fcwu/docker-ubuntu-vnc-desktop VNC approach
$ docker-compose down  # stop and delete the app
                        # images, volumes and source code remain
$ docker-compose down --volumes # remove the data volume used by the Redis container
$ docker-compose up -d
$ docker volume ls
$ docker-compose


# We can make changes to files in the volume, from the host side,
=== Firefox example ===
# and have them reflected immediately in the app.
[https://www.linkedin.com/pulse/running-gui-applications-docker-container-revathi-dhotre Running GUI Applications in Docker Container]
$ nano app.py  # do some changes
<pre>
$ docker volume inspect counterapp_counter-vol | grep Mount
From ubuntu:20.04
$ sudo cp app.py \
RUN apt update
  /var/lib/docker/volumes/counterapp_counter-vol/_data/app.py
RUN apt install firefox -y
# Our changes should be reflected
RUN apt install python3-pip -y
RUN pip3 install  notebook


$ docker-compose --help
CMD /usr/bin/firefox
</syntaxhighlight>
CMD jupyter-notebook --allow-root
</pre>
<pre>
nano Dockerfile
docker build -t gui .
docker run --env="DISPLAY" --net=host --name=firefox gui
</pre>
It works. However, I need to use '''docker rm -f firefox''' to kill it since Ctrl+c does not work.


=== Meld/gedit examples, save a running container as an image ===
<ul>
<li>[https://www.maketecheasier.com/run-gui-based-applications-docker/ How to Run GUI-Based Applications in Docker]
# Set Up Project Folder and Dockerfile '''nano dockerGUIFile'''
# Build the Docker Image '''sudo docker build -t mygedit:1 -f dockerGUIFile .'''
# Launch Docker Container with GUI Support Enabled '''xhost +local:docker''', '''docker run -it --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix mygedit:1'''
# Disconnect Docker from X Server '''xhost -local:docker'''
<li>[https://www.janert.org/blog/2022/running-a-gui-application-in-a-docker-container1 Running a GUI Application in a Docker Container]. It works. Below is a modified version for creating the '''meld''' app. I can save file modified by ''meld''. To use the app, I need to place files in the ~/Documents/docker (defined in '''-v'''). Note that the RAM usage is very minimal. Unfortunately on macOS, I got an error something related to Gtk.
<pre>
host> docker image pull ubuntu:jammy  # 22.04
host> docker container run --rm --net host -v /tmp/.X11-unix:/tmp/.X11-unix -it ubuntu:jammy
container# apt update
container# apt install -y meld
host> xhost +local:
container# export DISPLAY=:0


=== Docker-Compose persistent data MySQL ===
host> docker container ls  # find the ID of the running container
https://stackoverflow.com/questions/39175194/docker-compose-persistent-data-mysql
host> docker commit <ID> meld
container# exit


=== Connect to Docker daemon over ssh using docker-compose ===
host> docker container run --rm --net host \
[https://medium.com/@sujaypillai/dockertips-connect-to-docker-daemon-over-ssh-using-docker-compose-f4b189dd8951 #DockerTips: Connect to Docker daemon over ssh using docker-compose]
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  -v ~/Documents/docker:/meld \
  -e DISPLAY \
  --name=meld \
  meld meld
</pre>
</ul>


=== Dockerfile + docker-compose ===
=== R and httpgd package ===
[https://stackoverflow.com/a/29487120 Docker Compose vs. Dockerfile - which is better?]
<ul>
<li>[https://nx10.github.io/httpgd/articles/b03_docker.html httpgd Docker vignette], [https://nx10.github.io/httpgd/ installation] from Github.
<li>It works. However, currently "httpgs" is archived in CRAN (2023/1/25). So my temporary solution is
<pre>
$ docker run --rm -it r-base:4.2.2 bash
# apt update
# apt install  libfontconfig1-dev
# R
> install.packages("remotes")
> remotes::install_github("nx10/httpgd")
## note if we try to run 'httpgd::hgd(host = "0.0.0.0", port = 8888)', it does not work.
## The reason is we have not use "-p" option to expose a port in the previous "docker run" command


The Compose file describes the container in its running state, leaving the details on how to build the container to Dockerfiles.
## open another terminal and create a docker image based on the current container
$ docker ps -a | head
$ docker commit CONTAINER_ID httpgd:4.2.2
$ docker run --rm -it -p 8888:8888 httpgd:4.2.2 R
> httpgd::hgd(host = "0.0.0.0", port = 8888)
> plot(1:5)
</pre>
<li>It works when I tested it on a '''remote ubuntu server''' (R 4.4.0 & httpgd 2.0.1) (following the instruction on [https://cran.r-project.org/web/packages/httpgd/vignettes/b03_docker.html Docker vignette]). Either IP or hostname works but the hostname URL link given by httpgd::hgd() needs to be modified to include '''.local'''.
<li>Some variation of using hgd()
<pre>
hgd(host="0.0.0.0", port = 8888) # allow connection from any one from any computer
hgd()                # default is host=127.0.0.1, port will be random
hgd(token="secret")  # define the token


== Docker Swarm ==
hgd_browse()
* https://www.linux.com/learn/how-use-docker-machine-create-swarm-cluster
hgd_close()
* [https://www.howtoforge.com/tutorial/ubuntu-docker-swarm-cluster/ How Setup and Configure Docker Swarm Cluster on Ubuntu]
hgd_details()
hgd_url()
hgd_view()
</pre>
<li>To use it with [https://github.com/Bioconductor/bioconductor_docker?tab=readme-ov-file Bioconductor] (the Bioconductor docker image will use p3m.dev to install binary R packages so it is fast to create images), we can do like this
<pre>
$ docker run --rm -it -p 8888:8888 bioconductor/bioconductor_docker:RELEASE_3_18 R


== [https://mobyproject.org/ Moby Project] ==
> install.packages("httpgd")
[https://www.infoworld.com/article/3193904/containers/what-is-dockers-moby-project.html What is Docker's Moby Project?]
> httpgd::hgd(host = "0.0.0.0", port = 8888)
</pre>
OR use, for example, "bioconductor/bioconductor_docker:RELEASE_3_18" as the base image in the Dockerfile, and follow the same instruction from httpgd vignette to create a docker image.  
<pre>
$ nano Dockerfile_httpgd
$ docker build . -f Dockerfile_httpgd -t bioc-httpgd:RELEASE_3_18
$ docker images
$ docker run --rm -it --user rstudio -p 8888:8888 bioc-httpgd:RELEASE_3_18 R
</pre>
<li>[[Biowulf#Singularity|Singularity]]. The following is a definition file that is using the bioconductor image + the '''httpgd''' package.
<syntaxhighlight lang='sh'>
Bootstrap: docker
From: bioconductor/bioconductor_docker:RELEASE_3_18


= Applications =
%post
Some popular Linux applications such as: owncloud, lamp, openstack, node.js, roundcube, DLNA/Server, madsonic, webproxy/webfilter, DHCP/DNS-Server like dnsmasq, cloudprint, ...
    apt-get update \
    && apt-get install -y --no-install-recommends \
    libfontconfig1-dev \
    && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* \
    && install2.r --error --skipinstalled --ncpu -1 \
    httpgd \
    && rm -rf /tmp/downloaded_packages


* [https://kuonsam.miraheze.org/wiki/Setting_Up_a_Docker_Server#Install_Docker-compose Setting Up a Docker Server] (host OS is CentOS)
%runscript
    exec /usr/local/bin/R


== Dockerizing Compiled Software ==
%environment
https://ram.tianon.xyz/post/2017/12/26/dockerize-compiled-software.html
    export LC_ALL=C
</syntaxhighlight>
<syntaxhighlight lang='sh'>
sudo singularity build bioc.sif bioc.def
singularity run bioc.sif


== Data Science ==
> httpgd::hgd(host = "0.0.0.0", port = 8888)
[[Data_science#Container|Data Science]]
</syntaxhighlight>
After we copy the URL, we need to modify the IP or hostname.
</ul>


== Illumina BaseSpace ==
=== Docker-OSX ===
* http://blog.basespace.illumina.com/2013/10/21/introducing-the-native-app-engine/
https://github.com/sickcodes/Docker-OSX
* https://developer.basespace.illumina.com/docs/content/documentation/getting-started/overview
* https://developer.basespace.illumina.com/docs/content/documentation/native-apps/manage-docker-image


== Bioinformatics analyses ==
== Delete/remove/'''prune''' unused resources ==
* [https://www.biorxiv.org/content/early/2017/10/17/204495 Hot-starting software containers for bioinformatics analyses]
[https://docs.docker.com/config/pruning/ Prune unused Docker objects]
* [https://academic.oup.com/gigascience/article/6/8/1/3894236 Bio-Docklets: virtualization containers for single-step execution of NGS pipelines]


== Cloud provider ==
<ul>
Docker can be deployed on any cloud provider like Digital Ocean, Amazon Web Services (AWS), Microsoft Azure, Google Cloud Computing.
<li>How much disk space is Docker using?
<syntaxhighlight lang='bash'>
docker system df  # after calling 'docker buildx prune -f'
# TYPE            TOTAL    ACTIVE    SIZE      RECLAIMABLE
# Images          22        14        28.53GB  14.53GB (50%)
# Containers      15        10        41.01MB  39.58MB (96%)
# Local Volumes  7        3        1.025GB  223.9MB (21%)
# Build Cache    60        0        0B        0B
</syntaxhighlight>


* https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-docker-application
<li>Prune build cache if you are using standard Docker builds ('''seems most effective'''). Buildx/BuildKit stores intermediate layers and cache objects that are not removed by docker rmi. These can accumulate and take up a lot of space over time.  
* http://go.mkb.io/post/118463195802/docker-machine-with-digital-ocean
<syntaxhighlight lang='bash'>
* http://networkstatic.net/running-docker-machine-on-digital-ocean/
docker builder prune
* http://linoxide.com/linux-how-to/use-docker-machine-cloud-provider/
* [http://www.ithome.com.tw/news/106274 HTC採用AWS的三大原因]: 上市時間縮短、節省成本以及提供創新發想的低成本空間。


== ownCloud ==
docker system df  # Usually it is more than what Docker reports.
* https://hub.docker.com/_/owncloud/
* https://doc.owncloud.com/server/10.0/admin_manual/installation/docker/
* https://blog.securem.eu/serverside/2015/08/25/setting-up-owncloud-server-in-a-docker-container/
* [https://stackoverflow.com/questions/35137944/how-to-put-owncloud-behind-nginx-with-docker How to put ownCloud behind Nginx with Docker?]
* [https://www.blaize.net/2017/02/migrating-owncloud-to-docker/ Migrating ownCloud to Docker]
* "You are accessing the server from an untrusted domain" message when I use IP to access the server
** trusted_domains (config.php)
** https://forum.owncloud.org/viewtopic.php?t=34158
** https://blog.securem.eu/serverside/2015/08/25/setting-up-owncloud-server-in-a-docker-container/
** [https://youtu.be/KUZu5XG6cjI Fix ownCloud accessing the server from an untrusted domain]
** '''My simple fix''': use the IP instead of localhost when opening the browser to set up the first time


After I use '''docker run --rm --name myowncloud -p 81:80 owncloud:8.1''', I find I can only access it through http://localhost:81. If I try to access it through another computer by http://xxx.xxx.xx.1:81, the URL is changed back to http://localhost:81 so it failed to load.
sudo du -sh /var/lib/docker 
# shows the "actual" space on disk used by the entire Docker data directory,
# including: All images, containers, volumes, build cache, metadata, logs,
# overlay filesystems, network configs, and possibly orphaned or dangling
# data not accounted for by Docker’s internal tracking.  
</syntaxhighlight>


== nextcloud ==
<li>Prune build cache if you are using '''Buildx''' (for example, with docker buildx build), you should use docker buildx prune to manage its cache.
* https://hub.docker.com/_/nextcloud/
<syntaxhighlight lang='bash'>
* https://github.com/nextcloud/docker
docker buildx prune -f
* [https://apps.nextcloud.com/ App store]
</syntaxhighlight>
* [https://doc.owncloud.org/server/8.1/admin_manual/installation/apps_management_installation.html Installing and Managing Apps]
* Based on [https://github.com/owncloud owncloud's github repositories] or [https://github.com/nextcloud nextcloud's github repositories], android app has been updated more often than ios app.


I feel nextcloud is a little modern than owncloud though their interface are very similar. I got the same problem (URL is changed from IP to localhost) when I try to access its web from another computer. '''Using the IP instead of localhost to finish the initial setup can fix the error'''.
<li>Prune containers
<syntaxhighlight lang='bash'>
docker container prune # remove all containers that are not in ''running'' status
                      # Docker will ask for confirmation before deleting the containers


Note:
docker container prune -f
* The first we open the webpage, we need to create the admin username/password.
docker container rm -f $(docker container ls -aq) # remove even the running containers
* Nextcloud uses owncloud mobile application.
</syntaxhighlight>
* Nextcloud includes a small mp4 file. I can use browser to play mp4. Photos files can be opened in browsers too (including slideshow).


=== [https://apps.nextcloud.com/ Nextcloud Apps] ===
<li>Prune '''dangling images''': Dangling images are images that aren’t tagged and aren’t referenced by any container. Normal but unused/unreferenced images are kept and won't be deleted. See [[#%3Cnone%3E:%3Cnone%3E_images|<none>:<none>images]].  
For mp3, no apps are shipped with nextcloud.  
<syntaxhighlight lang='bash'>
docker image prune # unused image layers
</syntaxhighlight>
For example suppose you have created an image locally. If you don't like the new image created by docker build, simply remove it with '''docker rmi <new_image_name_or_id>'''. Any base images pulled during the build that are not used by other images can also be removed with: '''docker image prune'''.


* [https://apps.nextcloud.com/apps/audioplayer Audio Player]. When I play mp3 files, the web interface does not show a progress bar:( <syntaxhighlight lang='bash'>
<li>Remove all '''unused images''': If you want to remove all images that aren’t used by any existing containers, you can use the -a flag. It will give a warning saying: '''this will remove all images without at least one container associated to them'''. "Exited" container like "hello-world" will not be deleted.
$ docker run --rm --name mynextcloud -v ~/Downloads/nextcloudapps:/var/www/html/custom_apps -p 81:80 nextcloud
<syntaxhighlight lang='bash'>
# above will create an empty folder ~/Downloads/nextcloudapps (www-data:root)
docker image prune -a
$ tar xzvf Downloads/audioplayer-2.3.1.tar.gz -C Downloads/
$ docker cp Downloads/audioplayer mynextcloud:/var/www/html/custom_apps
# Go to nextcloud and '+Apps', a new app 'Audio Player' should have shown up.
</syntaxhighlight>
</syntaxhighlight>
* [https://apps.nextcloud.com/apps/music Music]. GOOD. The app is from the owncloud team though for some reason the app is not included in owncloud/nextcloud. Yes, a progress bar is shown when I played a song downloaded from Youtube:) <syntaxhighlight lang='bash'>
Used images means anyone shown by '''docker ps -a'''.
# No need to create a volume
 
$ docker run -d --name mycloud -p 81:80 nextcloud
<li>Prune volumes
<syntaxhighlight lang='bash'>
docker volume ls
docker volume prune # unused volumes by at least one container


# Open another terminal
docker volume prune --filter 'label=demo'
# Don't download the zip file from github. Get the zip file from the app store
docker volume prune --filter 'label=demo' --filter 'label=test'
$ tar xzvf ~/Downloads/music_0.7.0_nc-signed.tar.gz -C ~/Downloads/
</syntaxhighlight>
$ docker cp Downloads/music mycloud:/var/www/html/custom_apps
$ docker exec mycloud chmod -R 0750 /var/www/html/custom_apps
$ docker exec mycloud chown -R www-data:www-data /var/www/html/custom_apps
</syntaxhighlight> Now open the website. Click the gear icon (Settings) and click "Apps". Find out the 'music' app from the bottom of the list and click the 'Enable' button. A new Music icon will be created next to the Gallery icon at the top. Note: if we want to play music repeatedly, I should not play the music directly from Files. I should click the Music icon at the top and let it start to scan musics. Then once I can play a music from there, it will show two new icons; one is shuffle and the other is loop. To have a persistent data, we can 'run' using <syntaxhighlight lang='bash'>
$ mkdir -p ~/nextcloud/{html,apps,config,data}
$ docker run -d \
    --name mycloud \
    -p 81:80 \
    -v ~/nextcloud/html:/var/www/html \
    -v ~/nextcloud/apps:/var/www/html/custom_apps \
    -v ~/nextcloud/config:/var/www/html/config \
    -v ~/nextcloud/data:/var/www/html/data \
    nextcloud
</syntaxhighlight> If we like to delete the contain and its unamed volume, run <syntaxhighlight lang='bash'>
$ docker stop mycloud; docker rm -v mycloud
</syntaxhighlight> If we run the container again mounting all volumes, all apps,files,configuration,admin's username & password are kept.
* '''PDF viewer'''. PDF files will be downloaded instead of opening on the browser. This can be easily fixed. Click '+Apps' from the personal settings (the response is slow when I tested using Docker). Search for '''PDF viewer'''. Click the 'Enable' button (it will be changed to 'Disable' after that)
* [https://apps.nextcloud.com/apps/drawio draw.io]. After enable it, we can click the "+" sign and choose "Diagram" to create a new diagram (*.xml).
* [https://apps.nextcloud.com/apps/radio Radio]. After enable it, a new "Radio" icon will be shown at the top. Only 20 stations are available from the 'Top'. No response after I clicked "Categories".


== Use with R (r-base) & RStudio IDE: Rocker ==
<li>Prune networks
* [https://registry.hub.docker.com/_/r-base/ r-base] (Official image, R version is tagged)
<syntaxhighlight lang='bash'>
** [https://github.com/docker-library/docs Github] repository of the Official Docker Images.
docker network prune
** [https://colinfay.me/docker-r-reproducibility/ An Introduction to Docker for R Users]: how to write your own <Dockerfile>, install packages, run a script and get results.
** Extensions from r-base. For example, [https://github.com/rocker-org/rocker/issues/119 r-spatial-base]. It also mentions [https://registry.hub.docker.com/u/rocker/ropensci/ ropensci] container is built upon rocker/rstudio.
** The r-base image does not have pdflatex, git. Need to manually install them.
** Not sure if the Docker Official Image is the same as the one provided by Rocker Project.
** '''NOTE: Plotting just did not work insider a container'''. See [https://stackoverflow.com/q/44549656 Plotting R objects within docker container]. Search "Share your X11 display to the docker container" or the [https://github.com/rocker-org/rocker/wiki/Allowing-GUI-windows Wiki] from rocker. Creating graphics files inside a container is still OK 👌; see the example [https://jlintusaari.github.io/2018/07/how-to-compile-rmarkdown-documents-using-docker/ How to compile R Markdown documents using Docker].
: <syntaxhighlight lang='bash'>
docker pull r-base:3.5.3
docker run --net=host -it --rm r-base:3.5.3              # default is root "/"
docker run --net=host -v ~/Downloads:/src -it --rm r-base # /src does not exist
docker run --net=host -v ~/Downloads:/home/docker -it --rm r-base # /home/docker exists and is empty
</syntaxhighlight>
</syntaxhighlight>
* Dirk.eddelbuettel
** http://dirk.eddelbuettel.com/papers/useR2014_keynote.pdf
** http://dirk.eddelbuettel.com/papers/r_and_docker_sep2014.pdf
** [http://dirk.eddelbuettel.com/blog/2014/10/23/ Introducing Rocker: Docker for R]
** [http://dirk.eddelbuettel.com/blog/2019/08/05/#023_rocker_debug_example Debugging with Docker and Rocker – A Concrete Example helping on macOS]
** [https://arxiv.org/abs/2001.10641 The Rockerverse: Packages and Applications for Containerization with R]
* [https://www.rocker-project.org/ The Rocker Project] (<strike>only has the latest version</strike>)
** [https://github.com/rocker-org/rocker Github] repository.
** [https://github.com/rocker-org/rocker-versioned/blob/master/VERSIONS.md R, MRAN, RStudio Server versions correspondance]
** [https://github.com/rocker-org/rocker-versioned/blob/master/r-dependencies.md What dependencies are included in included in r-ver?]
* [https://github.com/rocker-org/rocker/wiki/Using-the-RStudio-image Using the RStudio image] includes the official instruction for the latest change. PS the default username is '''rstudio'''. <syntaxhighlight lang='bash'>
docker run -d -p 8787:8787 \
  -e PASSWORD=<password> \
  --name rstudio rocker/rstudio
# mount a local directory, change the username. A new directory /src will be created.
docker run -d -p 8787:8787 \
  -v ~/Downloads:/src \
  -e USER=<username>
  -e PASSWORD=<password> \
  --name rstudio rocker/rstudio


# Use R, without RStudio
<li>Clean up unused docker data. It remove
docker run -it -e DISABLE_AUTH=true rocker/rstudio:3.5.3 R
* all stopped containers
# Use Bash without RStudio, mount the current directory
* all networks not used by at least one container
docker run -it -e DISABLE_AUTH=true -v $(pwd):/home/rstudio/project rocker/rstudio:3.5.3 bash
* all dangling images
* unused build cache
<syntaxhighlight lang='bash'>
docker system prune
</syntaxhighlight>
</syntaxhighlight>
** [https://github.com/rocker-org/rocker/wiki/Sharing-files-with-host-machine Sharing files with host machine]
(More aggressive) Use '''docker system prune -a''' if we want to remove all images without at least one container associated to them.
** [http://www.magesblog.com/2014/09/running-rstudio-via-docker-in-cloud.html Running RStudio in cloud]
** [https://sbamin.com/blog/2016/02/running_rstudio_in_docker_environment/ Running RStudio in a docker container]
* [http://ropenscilabs.github.io/r-docker-tutorial/ R Docker tutorial] from ropenscilabs. It covers sharing your analysis.


=== Dockerfile ===
(Most aggressive; dangerous): '''docker system prune -a --volumes''' if we want to removes everything unused, including anonymous data volumes not used by at least one container.
Create a new directory and a new file 'Dockerfile' with the content.


<li>[https://linux.codidact.com/posts/292961 How to identify which Docker container an overlay is for?]
<pre>
<pre>
FROM debian:testing
DIRNAME=/var/lib/docker/overlay2
MAINTAINER Dirk Eddelbuettel [email protected]
for CONTAINER in $(docker ps -qa);
## Remain current
    do docker inspect $CONTAINER |grep -q $DIRNAME && docker ps -a |grep $CONTAINER;
RUN apt-get update -qq
done
RUN apt-get dist-upgrade -y
RUN apt-get install -y --no-install-recommends r-base r-base-dev r-recommended littler
RUN ln -s /usr/share/doc/littler/examples/install.r /usr/local/bin/install.r
</pre>
</pre>
</ul>


NOTE
== Plugins ==
# From [https://hub.docker.com/_/r-base r-base] in DockerHub click the "latest" in the "Supported tags and respective Dockerfile links" section.
[https://www.cloudsavvyit.com/15066/how-to-manage-docker-engine-plugins/ How to Manage Docker Engine Plugins]
# I ran into errors when I use the above (short) Dockerfile. But the Dockerfile from rocker (leave out the last line of launching R) works well. The R packages built in the image include 'docopt', 'magrittr', 'stringi', and 'stringr'.
# Install R package is possible when we launch a container. But we are not able to save the packages?? The [https://github.com/rocker-org/rocker/wiki rocker wiki] also mentions something about installing packages.
# See also [https://github.com/rocker-org/rocker/wiki/How-to-save-data How to save data] in wiki.


=== docker run ===
== Misc ==
Note that if we are using the Dockerfile above to create an image, we will be dropped to the Linux shell. If we are pulling the rocker/r-base image from Docker Hub, we will be in R console directly. See the last line of Dockerfile on [https://github.com/rocker-org/rocker/blob/master/r-base/Dockerfile github] website for rocker.
=== LXC (raw Linux containers) ===
 
* https://help.ubuntu.com/lts/serverguide/lxc.html
Then run the following to do some exercise (We could possibly replace 21b6a9e8b9e8 with your image ID or use ''rocker/r-base''). For simplicity, we can try the [http://cran.rstudio.com/web/packages/colortools/index.html colortools package] first which does not depend on other packages and there is no need to compile the package.
* https://help.ubuntu.com/community/LXC
<syntaxhighlight lang='bash'>
* https://askubuntu.com/questions/293275/what-is-lxc-and-how-to-get-started
sudo docker build -t debian:testing-add-r . # create an image based on the above Dockerfile
* [https://www.cyberciti.biz/faq/how-to-install-lxd-container-hypervisor-on-ubuntu-16-04-lts-server/ Setup Linux Container with LXC on Ubuntu 16.04]
wget http://cran.r-project.org/src/contrib/sanitizers_0.1.0.tar.gz
* [http://en.community.dell.com/techcenter/os-applications/w/wiki/6950.lxc-containers-in-ubuntu-server-14-04-lts LXC containers in Ubuntu Server 14.04 LTS]
sudo docker run -v `pwd`:/mytmp -t 21b6a9e8b9e8 \
* [https://blog.simos.info/trying-out-lxd-containers-on-our-ubuntu/ Trying out LXD containers on our Ubuntu]
    R CMD check --no-manual --no-build-vignettes /mytmp/sanitizers_0.1.0.tar.gz
sudo docker run -v `pwd`:/mytmp -t 21b6a9e8b9e8 \
    Rdevel CMD check --no-manual --no-build-vignettes /mytmp/sanitizers_0.1.0.tar.gz


sudo docker search eddelbuettel
==== LXC vs Docker ====
sudo docker pull eddelbuettel/docker-ubuntu-r  # default tag is 'latest'; actually older than the other tags
* https://diveintodocker.com/blog/why-i-got-started-with-docker
sudo docker images eddelbuettel/docker-ubuntu-r # see the tag column
* https://unix.stackexchange.com/questions/254956/what-is-the-difference-between-docker-lxd-and-lxc and https://i.stack.imgur.com/a5Neb.png
sudo docker pull eddelbuettel/docker-ubuntu-r:add-r # the tag name can only be obtained from hub.docker.com
sudo docker images eddelbuettel/docker-ubuntu-r # see the tag column
sudo docker pull eddelbuettel/docker-ubuntu-r:add-r-devel
sudo docker images eddelbuettel/docker-ubuntu-r # see the tag column
sudo docker run -v `pwd`:/mytmp -t 54d865dbd2c9 R CMD check --no-manual --no-build-vignettes /mytmp/sanitizers_0.1.0.tar.gz


sudo docker run -t -i eddelbuettel/docker-ubuntu-r /bin/bash
=== Vagrant vs Docker ===
$ sudo docker images
* http://stackoverflow.com/questions/16647069/should-i-use-vagrant-or-docker-io-for-creating-an-isolated-environment
REPOSITORY                    TAG                IMAGE ID            CREATED            VIRTUAL SIZE
* https://deliciousbrains.com/vagrant-docker-wordpress-development/
debian                        testing-add-r      21b6a9e8b9e8        28 minutes ago      572.2 MB
** Vagrant is easier to understand and is easier to get up and running but can be very resource intensive (in terms of RAM and space).
ubuntu                        14.04              ed5a78b7b42b        4 days ago          188.3 MB
** Docker’s architecture is harder to understand and can be harder to get up and running but is much faster, uses much less CPU and RAM and potentially uses much less space than Vagrant VM’s.
ubuntu                        latest              ed5a78b7b42b        4 days ago          188.3 MB
* https://youtu.be/9QGkJvbLpRA?t=3m22s
debian                        testing            88ba2870bfbe        7 weeks ago        154.7 MB
** Docker uses container technology while vagrant uses virtual machines.
eddelbuettel/docker-ubuntu-r  add-r-devel        c998a74a1fb4        11 weeks ago        460.4 MB
** If security is a concern, use vagrant and virtual machine
eddelbuettel/docker-ubuntu-r  add-r              54d865dbd2c9        11 weeks ago        460.4 MB
** For speeding development and sharing, use Docker.
eddelbuettel/docker-ubuntu-r  latest              a7cd5ddeb98e        5 months ago        515.4 MB
** Most teams use both to run a smooth operation


sudo docker logs xxxxx                # view the log
=== Date/Time zone ===
sudo docker restart xxxxx
* List of time zone. [https://docs.diladele.com/docker/timezones.html Setting Local Time in Docker]; e.g. "America/New_York" or "US/Eastern".
sudo docker exec -it xxxx /bin/bash   # view any changes in R library
* https://stackoverflow.com/questions/22800624/will-docker-container-auto-sync-time-with-the-host-machine
sudo docker stop xxxxx
<syntaxhighlight lang='bash'>
sudo docker docker rm xxxxx
docker run --rm -t -i -v /etc/localtime:/etc/localtime:ro ubuntu date
</syntaxhighlight>
</syntaxhighlight>
* https://serverfault.com/questions/683605/docker-container-time-timezone-will-not-reflect-changes


[https://hub.docker.com/r/dennishazelett/motifbreakr/ This] is another example of using 'docker run' accompanying [https://github.com/Simon-Coetzee/MotifBreakR MotifBreakR] package.
=== Access the internet from the container ===
Run the container with the '--net=host' option
<syntaxhighlight lang='bash'>
sudo docker run --net=host -it ubuntu /bin/bash
</syntaxhighlight>


=== Testing R packages ===
=== How to transfer/copy an image to another host ===
* [http://cran.rstudio.com/web/packages/RColorBrewer/index.html RColorBrewer] (pure R)
[https://stackoverflow.com/a/23938978 How to copy Docker images from one host to another without using a repository]
* [http://cran.rstudio.com/web/packages/digest/index.html digtest] (need compile, with vignette) [https://github.com/eddelbuettel/digest github source]
<syntaxhighlight lang='bash'>
* [http://cran.rstudio.com/web/packages/randomForest/index.html randomForest] (need compile & has suggests RColorBrewer)
# Step 1: save the Docker image as a tar file:
docker save -o <path for generated tar file> <image name>


=== Docker for R Package Development ===
# Step 2: copy your image to a new system with regular file transfer tools such as cp or scp.  
http://www.jimhester.com/2017/10/13/docker/


=== A DevOps Perspective ===
# Step 3: After that you will have to load the image into Docker:
* https://www.opencpu.org/posts/opencpu-with-docker/
docker load -i <path to image tar file>
</syntaxhighlight>
The tar file size is the same as what we get from 'docker image'. If we use the 'gzip' utility, it can reduce the file size (e.g 2.7GB to 1.1GB).


=== Reproducible ===
Or https://stackoverflow.com/a/39716019
* [https://datawookie.netlify.com/blog/2019/08/r-docker-and-checkpoint-a-route-to-reproducibility/ R, Docker and Checkpoint: A Route to Reproducibility]
<syntaxhighlight lang='bash'>
* [https://cran.r-project.org/web/packages/liftr/index.html liftr]: Persistent reproducible reporting by containerization of R Markdown documents
# Step 1:
 
docker save docker-image-name | gzip > my-image.tar.gz
I am not successful running the example in vignette. <syntaxhighlight lang='rsplus'>
# Step 3:
> render_docker(input)
docker load < my-image.tar.gz
Sending build context to Docker daemon  6.144kB
Step 1/8 : FROM rocker/r-base:latest
---> 4e232e9b4097
Step 2/8 : MAINTAINER Nan Xiao <me@nanx.me>
---> Running in f75404db590a
Removing intermediate container f75404db590a
---> ceae0a54648c
Step 3/8 : RUN  rm -f /var/lib/dpkg/available  && rm -rf  /var/cache/apt/*  && apt-get update -qq  && apt-get install -y
  --no-install-recommends    ca-certificates    libssl-dev    libcurl4-openssl-dev    libxml2-dev    git
---> Running in 8a4324cc7c53
W: Failed to fetch http://deb.debian.org/debian/dists/testing/InRelease  Temporary failure resolving 'deb.debian.org'
W: Failed to fetch http://http.debian.net/debian/dists/sid/InRelease  Temporary failure resolving 'http.debian.net'
W: Some index files failed to download. They have been ignored, or old ones used instead.
Reading package lists...
E: The value 'testing' is invalid for APT::Default-Release as such a release is not available in the sources
</syntaxhighlight>
</syntaxhighlight>


=== Debugging R memory problem ===
=== Where are Docker containers/images stored on the host: /var/lib/docker ===
[https://hub.docker.com/r/wch1/r-debug/ Docker image for debugging R memory problems] (valgrind)
* http://stackoverflow.com/questions/19234831/where-are-docker-images-stored-on-the-host-machine
* https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-storage-driver
* http://stackoverflow.com/questions/21016210/function-of-docker-directory-structure-in-var-lib-docker
* [https://foxutech.com/manage-docker-images-local-disk/ How to Manage Docker images on local disk]
* [https://www.howtogeek.com/devops/how-to-store-docker-images-and-containers-on-an-external-drive/ How to Store Docker Images and Containers on an External Drive]
* [https://linuxiac.com/how-to-change-docker-data-directory/ How to Change Docker’s Default Data Directory]


=== Debugging with gcc problem ===
The default is '''/var/lib/docker'''. The location can be changed by modifying the file '''/etc/default/docker'''. Three options if we are tight on the disk space.
https://twitter.com/eddelbuettel/status/1232341601483182081


=== More examples ===
'''1. Create a softlinks''' for the Docker data directory (/var/lib/docker) and for /var/lib/docker/tmp as described at [https://docs.docker.com/engine/reference/commandline/dockerd/#miscellaneous-options miscellaneous-options]. See [https://stackoverflow.com/a/40919928 this]. See [https://stackoverflow.com/a/40192707 for how to stop docker daemon] on different OS.
* [[#Docker|R -> Docker]]
<syntaxhighlight lang='bash'>
* [https://www.rplumber.io/docs/hosting.html#docker Plumber] package
sudo service docker stop  # or sudo systemctl stop docker
sudo mv /var/lib/docker /a/new/location
sudo ln -s /a/new/location /var/lib/docker # Create a symbolic link
sudo service docker start  # or sudo systemctl start docker
</syntaxhighlight>


=== Building a Repository of Alpine-based Docker Images for R ===
'''2. Change the default location to another place'''. For example,
* [https://velaco.github.io/my-dockerfile-for-r-shiny-based-on-alpine-linux/ Part I]
<syntaxhighlight lang='bash'>
* [https://velaco.github.io/my-dockerfile-for-r-shiny-based-on-alpine-linux-II/ Part II]
sudo nano /etc/default/docker
 
# Add a line DOCKER_OPTS="-g /home/brb/Docker"
=== RStudio in Docker – now share your R code effortlessly! ===
</syntaxhighlight>
https://harini.blog/2019/05/25/rstudio-and-rshiny-in-docker/
Then after running ''sudo service docker.io restart'' and then a simple pull '''sudo docker pull rocker/r-base''' or '''sudo docker run --rm -ti rocker/r-base''' (the Dockerfile of r-base is available on [https://github.com/rocker-org/rocker/blob/master/r-base/Dockerfile github.com], '''--rm''' option means Automatically remove the container when it exits), we will see something like this:
 
<syntaxhighlight lang='bash'>
It is interesting the Dockerfile uses littler's install2.r to install R packages. See http://dirk.eddelbuettel.com/code/littler.examples.html.  
$ docker run --rm -ti rocker/r-base
$ docker images
$ docker -v
Docker version 1.0.1, build 990021a


Note that the tag name should be lower case; awesomer instead awesomeR.
$ docker -D info | grep Root
Root Dir: /home/brb/Docker/aufs
</syntaxhighlight>


Also got an error when trying to build the image: ''Failed to fetch http://deb.debian.org/debian/dists/stretch/InRelease  Temporary failure resolving 'deb.debian.org' ''.
=== Consuming Docker system events ===
<syntaxhighlight lang='bash'>
# Open a new terminal
docker system events
# This command is a blocking command.  
# Thus, when you execute it in your terminal session the according session is blocked.


Try it again at home. The ''apt update'' part is OK but I still got a new error: ''Error: installation of package ‘gifski’ had non-zero exit status''
# Open another terminal
docker container run --rm alpine echo "Hello World"
</syntaxhighlight>


=== METACRAN web ===
=== Monitor tools ===
https://github.com/metacran/metacranweb It works (2019-11-3).
* [https://www.2daygeek.com/ctop-a-command-line-tool-for-container-monitoring-and-management-in-linux/# cTop – A Command-Line Tool For Container Monitoring And Management In Linux], [https://github.com/bcicen/ctop ctop]


=== Modified Dockerfile ===
== [https://docs.docker.com/machine/overview/ Docker Machine] ==
[https://joachim-gassen.github.io/2020/05/checking-your-package-for-compatibility-with-r-4/ Checking your Package for Compatibility with R 4.0.0]
Docker Machine is a tool that lets you
* Install Docker Engine on virtual hosts. You can use Machine (a unified way) to create Docker hosts on your local Mac or Windows box, on your company network, in your data center, or on cloud providers like Azure, AWS, or Digital Ocean. See the comment on [https://sreeninet.wordpress.com/2015/05/31/docker-machine/ here].
* Provision and manage multiple remote Docker hosts
* Provision Swarm clusters


== [http://www.bioconductor.org/help/docker/ Bioconductor] ==
Docker machine is not installed in Linux when you install Docker. See the instruction on [https://docs.docker.com/machine/install-machine/ here] to install it.
(2020-1-30)
* https://bioconductor.org/help/docker/
* https://hub.docker.com/r/bioconductor/bioconductor_docker


(2019-10-15)  
My feeling is if we just want to play Docker on a local Linux machine, we don't really need to use Docker Machine (it just make life more complicated). But if we are working on Mac/Windows or we want to work on clouds or test on VirtualBox, we shall use Docker machines.
* [https://hub.docker.com/r/bioconductor/bioconductor_full bioconductor_full]
* [https://seandavi.github.io/post/build-linux-r-binary-packages/ Building R Binary Packages for Linux]


[https://medium.com/@nitesh.turaga/how-i-use-bioconductor-with-docker-ca9d17d87771 How I use Bioconductor with Docker], [https://medium.com/@nitesh.turaga/how-i-use-bioconductor-with-docker-part-2-more-memory-faster-bioconductor-with-docker-fd7e69dce2bf Part 2: More memory, faster Bioconductor with Docker]
[https://youtu.be/OWhhOQAiGt0 Use Docker-machine to Create Docker Servers]. Compare the Docker images on the local machine (server 1) & a new host (server 2) created by '''docker-machine'''. Question: 1. how to tell we are in the host/machine environment? 2. how to exit the host environment after we use ''eval $() command? docker-machine stop MachineName.
 
<pre>
=== [https://github.com/Bioconductor-notebooks/BiocImageBuilder BiocImageBuilder] ===
$ docker-machine help
[http://www.rna-seqblog.com/reproducible-bioconductor-workflows-using-browser-based-interactive-notebooks-and-containers/ Reproducible Bioconductor workflows using browser-based interactive notebooks and containers]
$ docker-machine create --driver=virtualbox test
# Follow its hint on the output, issue the following command
$ docker-machine env test
# Follow its hint on the output, issue the following command
$ eval$(docker-machine env test) # will configure the docker CLI to connect to this docker machine 'test'
                                # This is equivalent to running 4 export commands on the command line
$ docker-machine ls  # Very useful
$ docker-machine stop test
$ docker-machine ip test
$ docker-machine start test
$ docker-machine rm test
</pre>


=== Bioc Conference ===
[https://youtu.be/rnaLmSkZfKk Play Docker Machine on Mac with Virtualbox]. Docker can be used to create a virtual machine just like Vagrant.
* [https://github.com/Bioconductor/BiocWorkshops2019/blob/master/README.md Bioc2019 conference]. [http://biocworkshops2019.bioconductor.org.s3-website-us-east-1.amazonaws.com/ Workshopt material]. Before the meeting (6/20/2019) there are 13 downloads and it bumps to 32 downloads after the meeting for [https://hub.docker.com/r/seandavi/bioc_2019 the docker image].
<pre>
** Download a tarball containing R packages (binary). 605 packages are included. It bundles 605 packages based on R 3.6.0 and Bioconductor 3.10 (BiocManager 1.30.4).
$ docker-machine create -d virtualbox demo
** Run RStudio container. All R packages downloaded in the last step are mounted. (user=rstudio, ps=bioc). That is, built-in is at '''/usr/local/lib/R/library''', custom is at '''/usr/local/lib/R/site-library'''. These two locations are what '''.libPaths()''' gives.
$ docker-machine ls


== Docker for Shiny Server ==
# first way to access a Docker host
* https://hub.docker.com/r/rocker/shiny/. Pay attention to the [https://hub.docker.com/r/rocker/shiny/~/dockerfile/ Dockerfile] there.
$ docker-machine ssh demo
* [http://docs.rstudio.com/shiny-server/ Shiny Administrator Guide]
docker@demo:~$ docker images # empty for now
* [https://docs.docker.com/engine/reference/commandline/run Docker Reference]. See Engine (docker) CLI from their LHS.
* [http://www.flaviobarros.net/2015/04/30/dockerizing-a-shiny-app/ Dockering a shiny app]
* Question: what happened if there is a new version of R or shiny-sever?


<syntaxhighlight lang='bash'>
# second way to access  
# specify --name so we don't need to use container id to access it later
$ docker-machine env demo
$ docker run -d --name rshiny -p 81:3838 rocker/shiny
$ eval $(docker-machine env demo)
$ docker version
</pre>


$ docker ps -l
[http://rancher.com/rancher-os/ RancherOS demo video] used the '''docker-machine''' command to pull and run the RancherOS.
 
<pre>
# Run in container's bash
docker-machine create -d virtualbox --virtualbox-boot2docker-url https://releases.rancher.com/os/latest/rancheros.iso demo
# https://stackoverflow.com/questions/30172605/how-to-get-into-a-docker-container
docker-machine ssh demo
# non-interactive
ps
$ docker exec -it rshiny ip addr 
docker ps
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
sudo system-docker ps
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever
22: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 scope global eth0
      valid_lft forever preferred_lft forever
 
# interactive shell
$ docker exec -it rshiny bash
root@5b78988d5619:/# who
root@5b78988d5619:/# which R
/usr/bin/R
root@5b78988d5619:/# ls /home
docker shiny
root@5b78988d5619:/# ls /srv/shiny-server
01_hello  02_text  03_reactivity  04_mpg  05_sliders  06_tabsets  07_widgets  08_html  09_upload  10_download  11_timer  index.html  sample-apps
root@5b78988d5619:/# R -e 'package.Description("glmnet")'
root@5b78988d5619:/# exit
 
$ docker stop rshiny
$ docker rm rshiny  # remove the container
</syntaxhighlight>


It is also useful to use the '''-v''' option in '''docker run''' so the local directory (eg /srv/shinyapps/) can be mapped to the docker volume (/srv/shiny-server).
sudo ros help
<syntaxhighlight lang='bash'>
sudo ros console list
# Put your shiny app in host's /srv/shinyapps/appdir,
sudo ros console switch ubunu
$ docker run -d -p 81:3838 \
apt-get help
    -v /srv/shinyapps/:/srv/shiny-server/ \
    -v /srv/shinylog/:/var/log/shiny-server/ \
    rocker/shiny
</syntaxhighlight>
And check running status
<pre>
$ docker ps -a
</pre>
 
=== Check opened ports ===
See [[Linux#What_network_ports_are_open:_lsof_or_netstat|What network ports are open: lsof or netstat]].
<pre>
$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address          Foreign Address        State     
tcp        0      0 0.0.0.0:22              0.0.0.0:*              LISTEN   
tcp        0      0 127.0.0.1:25            0.0.0.0:*              LISTEN   
...
tcp6      0      0 :::80                  :::*                    LISTEN   
tcp6      0      0 :::81                  :::*                    LISTEN   
tcp6      0      0 :::22                  :::*                    LISTEN   
tcp6      0      0 ::1:25                  :::*                    LISTEN
</pre>
</pre>


== Nginx ==
== Package CLI Applications ==
* [https://www.digitalocean.com/community/tutorials/how-to-run-nginx-in-a-docker-container-on-ubuntu-14-04 How To Run Nginx in a Docker Container on Ubuntu 14.04]. It teaches to put the whole web site in the host directory and the nginx configuration in the local host. You can edit the default file locally (to serve a new directory), or to use a '''proxy_pass''' to forward the traffic to another app/container like you would with a regular Nginx installation).
[https://www.cloudsavvyit.com/15713/how-to-use-docker-to-package-cli-applications/ How to Use Docker to Package CLI Applications]
* [https://www.digitalocean.com/community/tutorials/docker-explained-how-to-containerize-and-use-nginx-as-a-proxy How To Containerize and Use Nginx as a Proxy]
* [https://blog.docker.com/2015/04/tips-for-deploying-nginx-official-image-with-docker/ TIPS FOR DEPLOYING NGINX (OFFICIAL IMAGE) WITH DOCKER]
* [https://linux.cn/article-8932-1.html Docker 快速入门]
* [https://www.linux.com/learn/intro-to-linux/2017/11/how-install-and-use-docker-linux How to Install and Use Docker on Linux] Reverse-proxy, LetsEncrypt ... built in.
<syntaxhighlight lang='bash'>
docker run --name docker-nginx -p 80:80 nginx
</syntaxhighlight>


== httpd/apache ==
== Stack ==
https://hub.docker.com/_/httpd/
* https://www.composerize.com/
* [https://youtu.be/-ttZjGBkLL8 Export Docker Container Settings as Docker Compose Stack], [https://github.com/Red5d/docker-autocompose docker-autocompose] (only x86)


* [https://www.tecmint.com/install-apache-web-server-in-a-docker-container/ How to Setup a Simple Apache Web Server in a Docker Container]
== Docker app ==
* [https://codingbee.net/docker/docker-an-apache-hello-world-example Docker – An apache ‘hello world’ example]
Docker App is an experimental Docker feature which lets you build and publish application stacks consisting of multiple containers. It aims to let you share '''Docker Compose''' stacks with the same ease of use as regular Docker containers.


== Tomcat ==
[https://www.cloudsavvyit.com/10673/how-to-use-docker-app-to-containerise-an-entire-application-stack/ How to Use 'Docker App' to Containerise an Entire Application Stack]
https://hub.docker.com/_/tomcat/


== Jenkins for continuous integration ==
== Docker Swarm ==
* https://www.tutorialspoint.com/jenkins/jenkins_overview.htm
* https://www.linux.com/learn/how-use-docker-machine-create-swarm-cluster
* https://jenkins.io/doc/book/installing/
* [https://www.howtoforge.com/tutorial/ubuntu-docker-swarm-cluster/ How Setup and Configure Docker Swarm Cluster on Ubuntu]
* Example: https://dev.ropensci.org/
* [https://www.cloudsavvyit.com/13049/what-is-docker-swarm-mode-and-when-should-you-use-it/ What is Docker Swarm Mode and When Should You Use It?]


== MySQL ==
== Security ==
* https://hub.docker.com/r/mysql/mysql-server/
<ul>
* [https://dev.mysql.com/doc/mysql-installation-excerpt/5.7/en/linux-installation-docker.html Deploying MySQL on Linux with Docker]
<li>[https://cloudberry.engineering/article/dockerfile-security-best-practices/ Docker Security Best Practices from the Dockerfile]
* Note it seems impossible to use the 'grant' command interactively within the MySQL docker container.
<li>[https://www.cloudsavvyit.com/12631/how-to-secure-sensitive-data-with-docker-compose-secrets/ How to Secure Sensitive Data With Docker Compose Secrets]
* https://dzone.com/articles/using-docker-to-create-a-mysql-server <syntaxhighlight lang='bash'>
<li>[https://docs.docker.com/scout/ Docker Scout]. Docker Scout lets users secure their software supply chain and continuously observe and improve their security posture. Docker Scout is free for up to 3 repositories.
docker run --detach --name test-mysql --env="MYSQL_ROOT_PASSWORD=mypassword" mysql
<pre>
docker inspect test-mysql | grep IPAddress  # 172.17.0.2
docker login
docker scout enroll ORG_NAME


# https://dev.mysql.com/doc/index-other.html
docker scout scan my-web-app:latest
wget -O - http://downloads.mysql.com/docs/world.sql.gz | gunzip -c > world.sql


mysql -uroot -pmypassword -h 172.17.0.2 -e 'CREATE DATABASE world'
docker scout repo enable --org ORG_NAME ORG_NAME/scout-demo
cat world.sql | mysql -uroot -pmypassword -h 172.17.0.2 world
# Docker Scout analyzes the image you built most recently by default,
# zcat world.sql.gz | mysql -uroot -pmypassword -h 172.17.0.2 world
# so there's no need to specify the name of the image in this case.
mysql -uroot -pmypassword -h 172.17.0.2 -e 'USE world; SHOW TABLES'
</pre>
<li>[https://www.portainer.io/blog/is-docker-ce-ready-for-production-how-portainer-bridges-the-gaps Is Docker-CE Ready for Production? How Portainer Bridges the Gaps]
</ul>


mysql -uroot -pmypassword -h 172.17.0.2 -e 'DROP DATABASE world'
== [https://mobyproject.org/ Moby Project] ==
</syntaxhighlight>  <syntaxhighlight lang='rsplus'>
[https://www.infoworld.com/article/3193904/containers/what-is-dockers-moby-project.html What is Docker's Moby Project?]
# Let's see if we can access the database in R
system("sudo apt install libmysqlclient-dev")
library(RMySQL)
con <- dbConnect(MySQL(), "world", user="root", password="mypassword", host="172.17.0.2")
dbListTables(con)
head(dbReadTable(con, "city"))
head(dbReadTable(con, "country"))
head(dbReadTable(con, "countrylanguage"))


dbWriteTable(con, 'iris', iris)
== Windows container ==
# Error in .local(conn, statement, ...) :
* [https://stackoverflow.com/questions/45380972/how-can-i-run-a-docker-windows-container-on-osx How can I run a docker windows container on osx?]
#  could not run statement: The used command is not allowed with this MySQL version
* [https://linuxtldr.com/windows-docker-container/ Run Windows 11 in a Docker Container (Access it via the Browser)]
dbDisconnect(con)
** [https://github.com/dockur/windows dockurr/windows] Windows inside a Docker container.
</syntaxhighlight>
* [https://youtu.be/w_aVnMmrASE How To Create And Test MySQL Database Server in Docker On Ubuntu Linux] (video). Use Dockerfile.
* [https://severalnines.com/blog/mysql-docker-containers-understanding-basics MySQL Docker Containers: Understanding the basics], https://youtu.be/qJQPckRYNis?t=16m29s <syntaxhighlight lang='bash'>
# Fire up
docker run --detach --name=test-mysql --env="MYSQL_ROOT_PASSWORD=mypassword" mysql
docker ps -a


# Connecting to the Container
== When Not to Use Docker ==
docker inspect test-mysql | grep IPAddress
[https://www.cloudsavvyit.com/15446/when-not-to-use-docker-cases-where-containers-dont-help/ When Not to Use Docker: Cases Where Containers Don’t Help]
# sudo apt install mysql-client
# There are two methods to connect to the container
# method 1. https://hub.docker.com/r/mysql/mysql-server/
# docker exec -it test-mysql mysql -uroot -p
# method 2
mysql -uroot -pmypassword -h 172.17.0.20 -P 3306
docker run --detach --name test-wordpress --link test-mysql:mysql wordpress
docker exec -it test-wordpress bash
$ cat /etc/hosts


# Expose the MySQL container to the outside world
= Docker Compose <compose.yaml> =
# Access the MySQL container directly from the machine’s port 6603
Docker Compose can help us out as it allows us to specify a single file in which we can define our entire environment structure and run it with a single command (much like a Vagrantfile works).  
docker run --detach --name=test-mysql --env="MYSQL_ROOT_PASSWORD=mypassword" --publish 6603:3306 mysql
mysql -u root -pmypassword -h 127.0.0.1 -P 6603


# Configuration management
* Tabs are not allowed in a Docker Compose YAML file. You should use spaces for indentation instead.
mkdir -p /root/container/test-mysql/conf.d
* https://docs.docker.com/compose/ (the example will give an error when "RUN pip install -r requirements.txt")
nano /root/container/test-mysql/conf.d/my-custom.cnf
*# app.py
docker run \
*# requirements.txt
    --detach \
*# Dockerfile
    --name=test-mysql \
*# docker-compose.yml (old), compose.yml (new)
    --env="MYSQL_ROOT_PASSWORD=mypassword" \
* Some top-level '''keys''': version, services, networks, volumes
    --publish 6603:3306 \
* [https://stackoverflow.com/questions/38507446/docker-dockerfile-vs-docker-compose-yml Dockerfile vs docker-compose.yml]
    --volume=/root/docker/test-mysql/conf.d:/etc/mysql/conf.d \
* A simple example of running [https://www.tutorialspoint.com/docker/docker_compose.htm nginx & mysqsl]
    mysql
* [https://youtu.be/Qw9zlE3t8Ko Docker Compose in 12 Minutes]
mysql -uroot -pmypassword -h127.0.0.1 -P6603 -e 'show global variables like "max_connections"';
* https://deliciousbrains.com/vagrant-docker-wordpress-development/
docker run \
* https://github.com/kristophjunge/docker-mediawiki
    --detach \
* [https://www.howtoforge.com/tutorial/docker-guide-dockerizing-python-django-application/ Docker Guide: Dockerizing Python Django Application] (cannot follow)
    --name=test-mysql \
* Examples:
    --env="MYSQL_ROOT_PASSWORD=mypassword" \
** [https://github.com/docker/awesome-compose Awesome Docker Compose samples]
    --publish 6603:3306 \
** [https://github.com/haroldtreen/epub-press EpubPress] local server
    mysql \
** Running [https://github.com/nextcloud/docker nextcloud], [https://blog.ouseful.info/2017/06/16/rolling-your-own-jupyter-and-rstudio-data-analysis-environment-around-apache-drill-using-docker-compose/ Jupyter and RStudio]
    --max-connections=200 \
** [https://github.com/dceoy/docker-rstudio-server Rstudio]
    --character-set-server=utf8mb4 \
* [https://readmedium.com/docker-compose-for-beginners-working-with-multiple-containers-ee0727aab687 Docker Compose For Beginners: Working With Multiple Containers]
    --collation-server=utf8mb4_unicode_ci
** image, container_name
 
** image, container_name, environment
# Data Storage
** image, container_name, environment, volumes, ports
mkdir -p /storage/docker/mysql-datadir
docker run \
    --detach \
    --name=test-mysql \
    --env="MYSQL_ROOT_PASSWORD=mypassword" \
    --publish 6603:3306 \
    --volume=/root/docker/test-mysql/conf.d:/etc/mysql/conf.d \
    --volume=/storage/docker/mysql-datadir:/var/lib/mysql \
    mysql
docker inspect test-mysql
ls -al /storage/docker/mysql-datadir/
 
# If a MySQL container runs on top of an existing MySQL datadir,
# the $MYSQL_ROOT_PASSWORD variable should be omitted from the “run” command line;
docker stop test-mysql
docker rm -f test-mysql
docker run -d --name=another-new-mysql -p 6605:3306 -v /storage/docker/mysql-datadir:/var/lib/mysql mysql
docker logs another-new-mysql
</syntaxhighlight>
* [https://codereviewvideos.com/course/docker-tutorial-for-beginners/video/docker-mysql-tutorial Use Docker to run a typical MySQL server] from Code Review Videos <syntaxhighlight lang='bash'>
docker volume create crv_mysql


docker run \
== YAML validator ==
    -e MYSQL_ROOT_PASSWORD=my-secret-pw \
https://codebeautify.org/yaml-validator
    -e MYSQL_DATABASE=devdb \
    -e MYSQL_USER=dbuser \
    -e MYSQL_PASSWORD=dbpassword \
    --mount type=volume,src=crv_mysql,dst=/var/lib/mysql \
    -p 3306:3306 \
    -d \
    mysql:latest


# Alternatively we can put username/password in a text file for security
== Download binary ==
cat > .env <<EOF
<ul>
MYSQL_ROOT_PASSWORD=my-secret-pw
<li>https://github.com/docker/compose/releases for macOS (x86/arm), Linux (aarch64 or armv6 or armv7).
MYSQL_DATABASE=devdb
<li>New instruction [https://docs.docker.com/compose/install/linux/ Install the Compose plugin]. In short, we will use '''docker compose''' (new) instead of "docker-compose" (deprecated) command. There is no need to install the original "docker-compose" tool. "docker-compose --version"
MYSQL_USER=dbuser
</ul>
MYSQL_PASSWORD=dbpassword
EOF
docker run \
    --env-file .env \
    --mount type=volume,src=crv_mysql,dst=/var/lib/mysql \
    -p 3306:3306 \
    -d \
    mysql:latest
</syntaxhighlight>


=== Backup and restore ===
== Difference of "docker compose" and "docker-compose" ==
https://gist.github.com/spalladino/6d981f7b33f6e0afe6bb
* Docker-compose is the original '''Python-based''' command-line tool that was released in 2014. Docker compose is a newer '''Go-based''' command-line tool that is integrated into the Docker CLI platform and supports the compose-spec. Docker compose is meant to be a drop-in replacement for docker-compose, but it may have some behavior differences and new features. Docker compose is currently a tech preview, but it will eventually replace docker-compose as the recommended way to use Compose.
<syntaxhighlight lang='bash'>
# Backup
docker exec CONTAINER /usr/bin/mysqldump -u root --password=root DATABASE > backup.sql


# Restore
* https://docs.docker.com/compose/migrate/. From July 2023 Compose V1 stopped receiving updates. It’s also no longer available in new releases of Docker Desktop.
cat backup.sql | docker exec -i CONTAINER /usr/bin/mysql -u root --password=root DATABASE
* [https://forums.docker.com/t/docker-compose-vs-docker-compose/137884 Docker-compose vs docker compose]
</syntaxhighlight>
* [https://stackoverflow.com/a/66516826 Difference between "docker compose" and "docker-compose"]


=== Blog ===
== Simple examples ==
[https://www.howtoforge.com/tutorial/docker-guide-deploying-ghost-blog-with-mysql-and-traefik-with-docker/ Deploying Ghost Blog with MySQL and Traefik with Docker]
Create a file '''docker-compose.yml''' and run '''docker-compose up''' after creating the file.


== PostgreSQL ==
'''[https://hub.docker.com/_/hello-world hello-world]''': 9kB
[https://markheath.net/post/exploring-postgresql-with-docker Exploring PostgreSQL with Docker]
<pre>
version: "3"
services:
  hello:
    image: hello-world
</pre>


== Redis ==
'''[https://hub.docker.com/_/alpine alpine]''': 7.73MB
https://hub.docker.com/_/redis/
<pre>
version: "3"
services:
  server:
    image: alpine
    container_name: my_container
    command: sh -c "echo 'hello' && echo 'docker'"
</pre>


[https://github.com/metacran/metacranweb Web pages for metacran]
'''[https://hub.docker.com/_/nginx Nginx]''': 135MB
 
<pre>
[https://markheath.net/post/exploring-redis-with-docker Exploring Redis with Docker]
mkdir src
echo "Hello world!" > src/index.html
</pre>
<pre>
version: "3"
services:
  client:
    image: nginx
    ports:
      - 8000:80
    volumes:
      - ./src:/usr/share/nginx/html
</pre>


[http://collabnix.com/running-redis-inside-docker-container-on-jetson-nano/ Redis running inside Docker container on NVIDIA Jetson Nano], [https://redis.io/topics/ARM Redis is ideal for IoT and Embedded devices for several reasons].
== Composerize/convert a docker command into a docker compose file ==
* Copilot/ChatGPT/...
* https://www.composerize.com/
* [https://ostechnix.com/convert-docker-run-commands-into-docker-compose-files/ Convert Docker Run Commands Into Docker-Compose Files]


== Laravel ==
== An example from 'Fundamentals of Docker' ==
[https://www.howtoforge.com/tutorial/dockerizing-laravel-with-nginx-mysql-and-docker-compose/ Dockerizing Laravel with Nginx MySQL and Docker Compose on Ubuntu 18.04 LTS]
<syntaxhighlight lang='bash'>
git clone https://github.com/fundamentalsofdocker/labs.git
cd labs/ch08
docker-compose up
# Open http://localhost:3000/pet
</syntaxhighlight>
The images do not show up:( The terminal shows what has happened under the hood. So the problem is the http links for images do not exist.


== phpMyAdmin ==
We can also run the application in the background
* https://hub.docker.com/r/phpmyadmin/phpmyadmin/
<syntaxhighlight lang='bash'>
* [http://omarghader.github.io/docker-tutorial-phpmyadmin-and-mysql-server/ phpMyAdmin and MySQL server]
docker-compose up -d
</syntaxhighlight>


To stop and clean up the application, [https://www.thegeekstuff.com/2016/04/docker-compose-up-stop-rm/ Howto use docker-compose to Start, Stop, Remove Docker Containers]
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker run --name mysqlphp -e MYSQL_ROOT_PASSWORD=0000 -d mysql
docker-compose down # Stop and remove containers, networks, images, and unnamed volumes
docker run --name myadmin -d --link mysqlphp:db -p 8080:80 phpmyadmin/phpmyadmin
                    # defined in the docker-compose.yml flie
# OR
docker-compose down -v # similar to above but remove named volumes defined in yml file
# OR
docker-compose stop && docker-compose rm -f
docker-compose rm -v
</syntaxhighlight>
</syntaxhighlight>


Now go to your browser , tap http://localhost:8080 and login with root/0000.
If we also want to remove the volume for the database
 
'''ERROR''' mysqli_real_connect(): The server requested authentication method unknown to the client [caching_sha2_password]
 
The solution can be found [https://stackoverflow.com/questions/49948350/phpmyadmin-on-mysql-8-0 here]. After the change, I can log in phpMyAdmin.
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker exec -it mysqlphp bash
docker volume rm ch08_pets-data
 
mysql -u root -p0000
 
ALTER USER root IDENTIFIED WITH mysql_native_password BY '0000';
 
exit
exit
</syntaxhighlight>
</syntaxhighlight>


== MagicMirror ==
== An example from "How to Setup NGINX as Reverse Proxy Using Docker" ==
https://github.com/MichMich/MagicMirror/blob/master/README.md#docker
See [[#Nginx_reverse_proxy|here]]. Only nginx is used.


== Mail server ==
== An example from "Docker Deep Dive" (flask + redis) ==
[https://jzweig.com/blog/setup-your-own-email-server-with-docker/ Setup Your Own Email Server with Docker]
'''Note''' that on [https://docs.docker.com/compose/gettingstarted/#step-7-update-the-application Get started with Docker Compose] it mounts the current directory to ''/code'' inside the container. So after we modify ''app.py'', we don't need to copy it to the container.


== Mediawiki ==
Another one [https://takacsmark.com/docker-compose-tutorial-beginners-by-example-basics/ Docker compose tutorial for beginners by example]
* https://www.mediawiki.org/wiki/Docker
<syntaxhighlight lang='bash'>
* https://hub.docker.com/_/mediawiki/ or (better) https://docs.docker.com/samples/library/mediawiki/. The Dockerfile is based on [https://hub.docker.com/_/php/ jessie].
$ git clone https://github.com/nigelpoulton/counter-app.git
* https://github.com/kristophjunge/docker-mediawiki
$ cd counter-app
* [https://jzweig.com/blog/setup-mediawiki-and-postgres-with-docker/ Setup MediaWiki and Postgres with Docker] (based on simplyintricate/mediawiki, works on Mint). Visit http://localhost:8080 to see the result.
$ ls
<pre>
app.py  docker-compose.yml  Dockerfile  README.md  requirements.txt
$ ls -l ~/wiki_root
total 24
drwxr-xr-x 3 root    root    4096 Jul 10 10:09 data
drwxrwxr-x 3 brb      brb      4096 Jul 10 09:23 db
drwxrwxr-x 2 www-data www-data 4096 Jul 10 09:23 extensions
drwxrwxr-x 2 www-data www-data 4096 Jul 10 09:23 images
-rw-rw-r-- 1 www-data www-data 4152 Jul 10 11:12 LocalSettings.php
</pre>
* [https://github.com/besnik/tutorials/tree/master/docker-mediawiki Running Mediawiki as Docker container] (based on synctree/mediawiki, works tested on GalliumOS)
** Follow [https://github.com/besnik/tutorials/tree/master/docker-mysql Run MySql inside docker container] first. 1. Setup host to store configuration, data and dumps. The 'dumps' and 'initdb.d' folders are optional 2. Override default mysql configuration 3. Executing scripts and sql on container startup (optional) 4. Starting mysql container
** Visit http://IP_address:8080 to see the mediawiki page running on Docker
<pre>
brb@galliumos:~$ tree mysql
mysql
├── conf.d
│   └── mysql.cnf
├── data
│   ├── auto.cnf
│   ├── ca-key.pem
│   ├── ca.pem
│   ├── client-cert.pem
│   ├── client-key.pem
│   ├── ib_buffer_pool
│   ├── ibdata1
│   ├── ib_logfile0
│   ├── ib_logfile1
│   ├── ibtmp1
│   ├── mediawiki [error opening dir]
│   ├── mysql [error opening dir]
│   ├── performance_schema [error opening dir]
│   ├── private_key.pem
│   ├── public_key.pem
│   ├── server-cert.pem
│   ├── server-key.pem
│   ├── sys [error opening dir]
│   └── wikidb [error opening dir]
├── dumps
└── initdb.d


9 directories, 15 files
$ cat requirements.txt
flask


brb@galliumos:~$ tree -L 2 mediawiki/
$ cat Dockerfile
mediawiki/
FROM python:3.4-alpine
├── config
ADD . /code
│   └── LocalSettings.php
WORKDIR /code
├── extensions
RUN pip install -r requirements.txt
│   ├── Cite
CMD ["python", "app.py"]
│   ├── ConfirmEdit
│   ├── Gadgets
│   ├── ImageMap
│   ├── InputBox
│   ├── Interwiki
│   ├── LocalisationUpdate
│   ├── Nuke
│   ├── ParserFunctions
│   ├── PdfHandler
│   ├── Poem
│   ├── README
│   ├── Renameuser
│   ├── SpamBlacklist
│   ├── SyntaxHighlight_GeSHi
│   ├── TitleBlacklist
│   └── WikiEditor
└── images
    └── README


19 directories, 3 files
$ cat docker-compose.yml
</pre>
version: "3.5"
* https://linuxconfig.org/mediawiki-easy-deployment-with-docker-container (based on linuxconfig/mediawiki)
services:
* http://collabnix.com/how-to-setup-mediawiki-in-seconds-using-docker/ (based on appcontainers/mediawiki)
  web-fe:
* bitnami/mediawiki (too complicated)
    build: .
* [https://www.packtpub.com/books/content/isolated-mediawiki-setup-raspberry-pi-using-docker-part-1 Isolated MediaWiki Setup on the Raspberry Pi using Docker, Part 1]
    command: python app.py
    ports:
      - target: 5000
        published: 5000
    networks:
      - counter-net
    volumes:
      - type: volume
        source: counter-vol
        target: /code
  redis:
    image: "redis:alpine"
    networks:
      counter-net:


== [https://www.bookstackapp.com/ BookStack] ==
networks:
BookStack is a simple, self-hosted, easy-to-use platform for organising and storing information.
  counter-net:


https://github.com/solidnerd/docker-bookstack
volumes:
  counter-vol:


== Media server ==
$ docker-compose up &
=== Airsonic media server ===
https://airsonic.github.io/download/


My comment:
$ docker container ls
* Added mp3/mp4 files are not recognized.
* Cannot play by web browsers
* Special clients are needed:(


=== Plex ===
$ docker network ls
[https://github.com/plexinc/pms-docker Official Docker container for Plex Media Server]
NETWORK ID          NAME                    DRIVER              SCOPE
2acef6dabde6        bridge                  bridge              local
a2d42bc482ff        counterapp_counter-net  bridge              local
e1e093b64282        host                    host                local
7ecd0a6a9ebd        none                    null                local


My comment:
# Open the browser http://localhost:5000
* After starting, web browser cannot connect to it
$ docker-compose ps
      Name                      Command              State          Ports       
-------------------------------------------------------------------------------------
counterapp_redis_1    docker-entrypoint.sh redis ...  Up      6379/tcp             
counterapp_web-fe_1  python app.py                    Up      0.0.0.0:5000->5000/tcp


=== DockSTARTer: get started with home server apps running in Docker ===
$ docker-compose stop
* https://dockstarter.com/
$ docker-compose ps
* [https://www.makeuseof.com/tag/setup-linux-media-server/ How to Set Up a Linux Media Server in Under One Hour]
# We can see stopping a Compose app does not delete the application


== DNS server ==
$ docker container ls -a
[https://linuxconfig.org/protecting-your-privacy-with-firefox-on-linux#h4-1-private-dns Private DNS server container]
$ docker-compose rm    # delete a stopped Compose app
 
                        # images, volumes and source code remain
[https://www.howtoforge.com/tutorial/how-to-deploy-a-dynamic-dns-server-with-docker-on-debian-10/ How to Deploy a Dynamic DNS Server with Docker on Debian 10]
$ docker-compose restart
 
                        # If you made changes to your Compose app since stopping,
== Pi-hole ==
                        # these changes will not appear in the restarted app.
* https://hub.docker.com/r/pihole/pihole/, https://github.com/pi-hole/docker-pi-hole
                        # You need to re-deploy the app to get the changes.
* [https://pimylifeup.com/raspberry-pi-pi-hole/ Raspberry Pi Pi-Hole]: A Network Wide Ad-blocker
$ docker-compose ps
* [https://homenetworkguy.com/how-to/install-pihole-on-raspberry-pi-with-docker-and-portainer/ Install Pi-hole on a Raspberry Pi with Docker and Portainer]
$ docker-compose down  # stop and delete the app
 
                        # images, volumes and source code remain
== KeeWeb: password manager compatible with KeePass ==
$ docker-compose down --volumes # remove the data volume used by the Redis container
https://github.com/keeweb/keeweb
$ docker-compose up -d
 
$ docker volume ls
== Flask ==
$ docker-compose
[https://www.howtoforge.com/dockerizing-flask-application-using-docker-on-debian-10/ Dockerizing Flask Application Using Docker on Debian 10]
 
 
# We can make changes to files in the volume, from the host side,
== ONLYOFFICE ==
# and have them reflected immediately in the app.
* https://www.howtoforge.com/tutorial/how-to-install-onlyoffice-8.9.0-with-docker-on-ubuntu/
$ nano app.py  # do some changes
* https://www.howtoforge.com/tutorial/how-to-update-onlyoffice-to-version-95-with-docker/ This involves backing up and restoring MYSQL data.
$ docker volume inspect counterapp_counter-vol | grep Mount
$ sudo cp app.py \
  /var/lib/docker/volumes/counterapp_counter-vol/_data/app.py
# Our changes should be reflected
 
$ docker-compose --help
</syntaxhighlight>


== Gitlab ==
== Create Compose Files From Running Docker Containers ==
* https://docs.gitlab.com/omnibus/docker/
[https://www.makeuseof.com/create-docker-compose-files-from-running-docker-containers/ How to Automatically Create Compose Files From Running Docker Containers]
* https://hub.docker.com/r/gitlab/gitlab-ce/
* [https://www.howtoforge.com/tutorial/how-to-install-gitlab-server-with-docker-on-ubuntu-1804/ How to Install Gitlab Server with Docker on Ubuntu 18.04 LTS]


== NAS & Docker ==
== Docker-Compose persistent data MySQL ==
http://www.ithome.com.tw/tech/96500
https://stackoverflow.com/questions/39175194/docker-compose-persistent-data-mysql


Some examples
== Connect to Docker daemon over ssh using docker-compose ==
* GetLab專案管理工具
[https://medium.com/@sujaypillai/dockertips-connect-to-docker-daemon-over-ssh-using-docker-compose-f4b189dd8951 #DockerTips: Connect to Docker daemon over ssh using docker-compose]
* Jenkins開發版本管理工具


== Draw.io for diagrams and more ==
== Dockerfile + docker-compose ==
https://github.com/jgraph/drawio/tree/master/etc/docker
[https://stackoverflow.com/a/29487120 Docker Compose vs. Dockerfile - which is better?]


== Run a benchmark program on ARM devices ==
The Compose file describes the container in its running state, leaving the details on how to build the container to Dockerfiles.
* [http://www.element14.com/community/people/markfink/blog/2015/02/05/using-docker-on-beaglebone-black?CMP=SOM-EUROPE-MFINK-BBBlack Beaglebone black] as an example. More device examples can be found on [http://www.testing-software.org/internet_of_things.html http://www.testing-software.org/].


== Set up a Mastodon Instance on Linux ==
== How to deploy on remote Docker hosts with docker-compose ==
[http://www.makeuseof.com/tag/social-network-set-mastodon-instance-linux/ Your Own Social Network: How to Set Up a Mastodon Instance on Linux]
[https://www.docker.com/blog/how-to-deploy-on-remote-docker-hosts-with-docker-compose/ How to deploy on remote Docker hosts with docker-compose]


== Bioinformatics tools (Tophat, BWA, et al) ==
== logs ==
https://github.com/dceoy/docker-bio
<pre>
docker-compose logs -f
# Ctrl + c
</pre>


== GIVE - Genomic Interactive Visualization Engine ==
= GUI/TUI interface manager =
https://github.com/Zhong-Lab-UCSD/Genomic-Interactive-Visualization-Engine/blob/master/tutorials/GIVE-Docker.md
[https://www.tecmint.com/docker-tools/ 11 Must-Have Docker Tools To Simplify Your Workflow]:
* LazyDocker - Command-Line Docker Management
* Dive - Analyze Docker Image Layers
* Portainer – Simplify Docker Management
* Watchtower – Automated Docker Container Updates
* Dockly – Interactive Docker Management Tool
* Docker Compose – Define and Run Multi-Container Apps
* Dry – Real-time Docker Container Monitoring
* Sliplane – Cloud-Based Docker Management Tool
* Orbstack (closed source) - manage VM and Docker containers
* Docker Desktop – A Graphical Interface for Docker
* Visual Studio Code (VS Code) Docker Extension


== [https://www.elastic.co/ Elastic Search] ==
== [https://github.com/moncho/dry Dry] ==
* https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html
[https://www.2daygeek.com/dry-an-interactive-cli-manager-for-docker-containers/ Dry – An Interactive CLI Manager For Docker Containers]. The TUI is built on top of [https://github.com/gizak/termui termui]; a cross-platform, easy-to-compile, and fully-customizable terminal dashboard. It is inspired by [https://github.com/yaronn/blessed-contrib blessed-contrib], but purely in Go.
* https://docs.docker.com/samples/library/elasticsearch/
* https://github.com/triestpa/guttenberg-search


== Webpage monitor tools ==
== LazyDocker (TUI) ==
[https://github.com/statping/statping/wiki/Features statping]
* [https://github.com/jesseduffield/lazydocker Github]
* [https://www.linuxuprising.com/2019/07/lazydocker-new-docker-and-docker.html?m=1 LazyDocker: New Docker And Docker Compose Terminal UI]
* It works on ARM devices too.
* Video by [https://youtu.be/xb99lgO5Mw0?t=1083 Awesome open source]


= Orchestrator =
== Dockly (TUI) ==
== [https://www.docker.com/kubernetes Kubernete] ==
[https://www.ostechnix.com/dockly-manage-docker-containers-from-terminal/ Dockly – Manage Docker Containers From Terminal]
* [https://kodekloud.com/p/kubernetes-for-the-absolute-beginners-hands-on Kubernetes For The Absolute Beginner - Hands On] from kodekloud.com
 
* [http://docker-k8s-lab.readthedocs.io/en/latest/ Docker Kubernetes Lab Handbook] by Peng Xiao. The github page is on https://github.com/xiaopeng163/docker-k8s-lab.
== DockStation ==
* [https://youtu.be/2G-A6Knjrvo Introducing Kubernetes] by Marc Sluiter. Kubenetes can be used to schedule, run and manage containers in a cluster of virtual or physical machines.
It is not open source. It works with remote Docker containers.
** Starting by Google in 2014
** Pods: smallest unit of deployment. small group of tightly coupled containers. share network and data volumes. routable IP address. multiple pods per node.
* [https://youtu.be/6xJwQgDnMFE Create a 2-node Kubernetes cluster in 10 minutes]
** [https://github.com/kubernetes/dashboard Kubernetes Dashboard]
* [https://youtu.be/_vHTaIJm9uY Kubernetes Webinar Series - Getting Started with Kubernetes]
** https://thenewstack.io/tutorial-configuring-ultimate-development-environment-kubernetes/
** https://github.com/janakiramm/Kubernetes-dev-env
* [https://www.oreilly.com/ideas/how-to-manage-docker-containers-in-kubernetes-with-java Deploying Java Applications with Docker and Kubernetes]
* [https://blog.alexellis.io/docker-for-mac-with-kubernetes/ First impressions: Docker for Mac with Kubernetes]
* [https://github.com/kubernetes/minikube Minikube]: run Kubernetes locally
** [https://www.howtoforge.com/tutorial/how-to-install-kubernetes-with-minikube-on-ubuntu-1804-lts/ How to Install Kubernetes with Minikube on Ubuntu 18.04 LTS]
** [https://opensource.com/article/19/12/kubernetes-namespaces Kubernetes namespaces for beginners].  You need to have Minikube, Helm, and the kubectl command line installed.
* [https://www.biorxiv.org/content/10.1101/488643v2?rss=1 Galaxy-Kubernetes integration: scaling bioinformatics workflows in the cloud] Moreno et al 2019
* [https://seandavi.github.io/2019/03/helm-on-google-kubernetes-engine/ Helm on Google Kubernetes Engine] by Sean Davis
* [https://microk8s.io/ MicroK8s]
** [https://github.com/CanonicalLtd/multipass Multipass]
** [https://itnext.io/microk8s-on-macos-98f1de3aa63e MicroK8s on MacOS]


== Kubernete vs Docker swarm ==
* [https://github.com/DockStation/dockstation DockStation]
* https://platform9.com/blog/kubernetes-docker-swarm-compared/
* [https://www.upnxtblog.com/index.php/2018/01/17/top-6-gui-tools-for-managing-docker-environments/ TOP 6 GUI tools for managing Docker environments] 2018
* [https://www.ithome.com.tw/news/124290 DigitalOcean容器應用開發大調查:近半數開發者已採用]
* [https://www.how2shout.com/tools/4-best-docker-gui-tools-to-manage-containers-graphically.html 4 Best Docker GUI tools to manage containers graphically] 2019


== k3s: Lightweight Kubernetes ==
== DockSTARTer: get started with home server apps running in Docker ==
[https://opensource.com/article/20/3/kubernetes-raspberry-pi-k3s Run Kubernetes on a Raspberry Pi with k3s]
* https://dockstarter.com/
* [https://www.makeuseof.com/tag/setup-linux-media-server/ How to Set Up a Linux Media Server in Under One Hour]


= Other containers =
== [https://portainer.io/ Portainer]* (nice) ==
== [https://sylabs.io/ Singularity] and HPC systems ==
<ul>
* Old URL at [http://singularity.lbl.gov/ singularity.lbl.gov]  
<li>Username: admin. Password: at least 12 characters long.
* Singularity enables users to have full control of their environment; Singularity containers let users run applications in a Linux environment of their choosing. No 'sudo' is needed in general unless you want to build a container from a recipe.  
* URL looks like https://IP:9443/#!/auth
* Containers are more like an executable file for you to use
* It seems Chrome's password manager does not work on it.</li>
* Containers are stored under the current location. It does not have a centre location (like /etc/default/docker if we use docker) to store images.
<li>[https://github.com/portainer/portainer/issues/5406 Hardware minimum requirements] 100MB RAM. That's why 1GB ram of Raspberry Pi works fine.
* Can convert Docker containers to Singularity and run containers directly from Docker Hub
<li>[https://docs.portainer.io/start/install-ce/server/docker Install CE], [https://docs.portainer.io/ Documentation]
* These bind points cannot be created unless the path already exists within the container. To ensure access to these storage spaces and remedy bind point errors, create these directories in the %post section of your Bootstrap file.
<pre>
* [https://singularity-hub.org/ Singularity Hub]
docker volume create portainer_data
docker run -d -p 8000:8000 -p 9443:9443 \
  --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data portainer/portainer-ce:latest
</pre>
By default, Portainer Server will expose the UI over port 9443 and expose a TCP tunnel server over port 8000. The latter is optional and is only required if you plan to use the Edge compute features with Edge agents.
</li>
<li>Access https://localhost:9443 (it's https, not http)</li>
<li>Portainer itself is a docker application. </li>
<li>[https://docs.portainer.io/advanced/reset-admin Reset the admin user's password].</li>
<li>[https://youtu.be/M365jgJ0O2E How to Update Portainer Fast, Simple, and Easy Guide]. docker stop + docker rm + docker rmi + docker run.
</li>
* [https://youtu.be/2oi4IQF7VnE Raspberry Pi Home Server Episode 5: Remote Access with NGINX Proxy Manager]
* [https://youtu.be/ji0kgXhXR6g Raspberry Pi Home Server Episode 8: BitWardenRS - Password Manager with Remote Access] (video)
* [https://dbtechreviews.com/2020/07/install-nextcloud-on-a-raspberry-pi-4-with-openmediavault-and-docker/ Install NextCloud on a Raspberry Pi 4 with OpenMediaVault and Docker]
</li>
<li>[https://docs.portainer.io/start/upgrade/docker#community-edition Update] from the official document
{{Pre}}
docker stop portainer
docker rm portainer
docker pull portainer/portainer-ce:lts
 
docker run -d -p 8000:8000 -p 9443:9443 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:lts
</pre>
</ul>
* [https://github.com/portainer/portainer-docs/issues/91 Why port 8000 is needed to be published?], [https://forums.portainer.io/t/what-port-8000-used-for-do-i-need-to-expose-it/210 What port 8000 used for? Do I need to expose it?]
* [https://dzone.com/articles/a-comparison-of-docker-guis A Comparison of Docker GUIs]. A username/password is required to access the page unless we use the '''--no-auth''' option; see [https://portainer.readthedocs.io/en/stable/configuration.html Configuration].
* [https://www.howtoforge.com/tutorial/ubuntu-docker-portainer/ How to Manage Docker Containers using Portainer on Ubuntu 16.04]. Go to Local. It will show the status of all local stacks, containers, volumes and images. Very Cool!
* [https://www.linuxtechi.com/monitor-manage-docker-containers-portainer-part1/ Monitor and Manage Docker Containers with Portainer.io (GUI tool) – Part-1] 2019
* [https://www.cloudsavvyit.com/8911/how-to-get-started-with-portainer-a-web-ui-for-docker/ How to Get Started With Portainer, a Web UI for Docker]
* [https://www.linuxtechi.com/monitor-manage-docker-containers-portainer-io-part-2/ Monitor and Manage Docker Containers with Portainer.io (GUI tool) – Part-2]
* [https://collabnix.com/portainer-vs-rancher/ Portainer Vs Rancher]
* [https://youtu.be/XYcKmPi4McA How-to: Deploy Portainer on MicroK8s] (video)
* [https://www.portainer.io/blog/from-zero-to-production-with-fedora-coreos-portainer-and-wordpress-in-7-easy-steps From Zero to Production with Fedora CoreOS, Portainer, and WordPress in 7 Easy Steps]. Virtualbox was used


Ref:
=== IP address 0.0.0.0 ===
* [https://hpc.nih.gov/apps/singularity.html Singularity] at NIH/Biowulf. It needs to run 'module load singularity' first to load related commands.
[https://www.reddit.com/r/docker/comments/rkq7o8/comment/hpbb13k/ How to setup ip address in portainer to access containers?] </BR>
* NIH-HPC
(Left hand side) Administration -> Environment-related -> Environments > local (or whatever your environment is named) -> '''Public ip'''.
** [https://singularity-tutorial.github.io/ Tutorial] and its [https://github.com/NIH-HPC/Singularity-Tutorial Github] source ('''valuable''')
** [https://github.com/nih-byob/presentations/tree/master/2019/01_bioinformatics_tips Bioinformatics advice I wish I learned 10 years ago]
* [https://tin6150.github.io/psg/blogger_container_hpc.html DOCKER VS SINGULARITY VS SHIFTER VS UGE CONTAINER EDITION]
* [https://github.com/data61/gossamer xenome] case where the build instruction is good for Ubuntu 16.04. If we try to build under Ubuntu 14.04 (tested using docker run), we will get an error message '' CMake 3.1 or higher is required.  You are running version 2.8.12.2''.
* https://github.com/NIH-HPC/singularity-examples/blob/master/rnaseq/Singularity.rnaseq


'''Comparison of docker and singularity commands:'''
=== Templates ===
{| class="wikitable"
* [https://dbtechreviews.com/2020/09/using-application-templates-in-portainer-2-0/ Using Application Templates in Portainer 2.0]
|-
* [https://youtu.be/BwgKd6LohQo Install 80+ Docker Images In Seconds Using This Portainer App Template] (video)
! [https://docs.docker.com/edge/engine/reference/commandline/docker/ docker] !! [http://singularity.lbl.gov/user-guide singularity]
* [https://www.reddit.com/r/portainer/comments/v3uyo3/best_and_most_uptodate_portainer_app_template_for/?utm_source=share&utm_medium=web2x&context=3 Best and most up-to-date Portainer app template for selfhosting?] 2022-06-03
|-
** [https://github.com/mycroftwilde/portainer_templates mycroftwilde]
| $ docker pull ubuntu:latest <br/>$ docker pull broadinstitute/gatk3:3.8-0 || $ singularity pull docker://ubuntu:latest<br/>$ singularity pull docker://broadinstitute/gatk3:3.8-0
* [https://youtu.be/BwgKd6LohQo Install 80+ Docker Images In Seconds Using This Portainer App Template] (video, 2020)
|-
** Default on my Portainer 2.0.1 (see logs for version number) https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json
| $ docker build || $ singularity build
** https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/portainer-2.0/Template/template.json (working), [https://github.com/SelfhostedPro/selfhosted_templates Github]
|-
** https://raw.githubusercontent.com/nashosted/self-hosted-template/master/template.json (working)
| $ docker shell (not exist) || $ singularity shell docker://broadinstitute/gatk3-3.8-0<br/>  $ singularity shell gatk3-3.8-0.img<br/> > ls  # the default location depends on the host system<br/>
** Alternative: [https://github.com/Taisun-Docker/taisun taisun]
> ls /usr  # this is from the container <br/><br/>$ singularity shell --bind ~/Downloads:/mnt XXX.img<br/>$ singularity shell docker://ubuntu:latest<br/># container is ephemeral
|-
| $ docker run --name test -it ubuntu date <br/><br/># <span style="color: red">The next example is similar to 'singularity exec'</span><br/>$ docker run --rm -i -t \<br/>  -v $(pwd):/usr/my_data \<br/>  broadinstitute/gatk3:3.8-0 \<br/>  bash /usr/my_data/myscript.sh || $ singularity run gatk3-3.8-0.img date
|-
| $ docker run --name ubuntu_bash --rm -i -t ubuntu bash<br/>$ docker exec -d ubuntu_bash touch /tmp/execWorks || # <span style="color: red">Most useful</span><br>$ singularity exec gatk3-3.8-0.img java -version <br/>$ singularity exec xxx.img cat /etc/*release<br>$ singularity exec docker://rocker/tidyverse:latest R <br/>$ singularity exec docker://rocker/tidyverse:latest Rscript myScript.R<br/>
|}


=== Cache ===
== Yacht ==
When we run ''singularity exec docker://rocker/tidyverse:latest R'', it will save something in the cache in our system.
* https://yacht.sh/Installation/yacht/
* Yacht's [https://yacht.sh/docs/Pages/Dashboard Dashboard] page shows the resources used by each docker application (it seems Portainer can't)
* [https://youtu.be/KstIS5DstTE Yacht Installed on Docker - Portainer Alternative] (video)
* [https://youtu.be/c4rKWrH88F0?t=166 What's on my Home Server? MUST HAVE Services] (video)


It seems to be OK after I manually delete the directory $HOME/.singularity (tested in Biowulf).
== cockpit-docker ==
* [https://www.hostwinds.com/guide/installing-and-using-cockpit-docker-linux-vps/ Installing And Using Cockpit-Docker]
* The default port is 9090.  
* Not useful for manager docker containers.
<pre>
sudo apt-get -y install cockpit-docker


=== RStudio ===
sudo systemctl restart cockpit
* [https://rviews.rstudio.com/2017/03/29/r-and-singularity/ R and Singularity] by Bryan Lewis
</pre>
* [https://archive.sylabs.io/2018/10/rstudio-ide-and-server/ RStudio – IDE and Server powered by Singularity] by Jason Stover
* https://github.com/nickjer/singularity-rstudio and https://github.com/nickjer/singularity-r
* https://www.rocker-project.org/use/singularity/. It also includes how to run a SLURM job script.
* https://njstem.wordpress.com/2018/08/02/r-script-seurat-with-a-singularity-container-using-slurm/
* https://journal.r-project.org/archive/2017/RJ-2017-065/RJ-2017-065.pdf


<syntaxhighlight lang='bash'>
== [https://github.com/crosbymichael/dockerui DockerUI] (Deprecated, Development continues at Portainer) ==
$ singularity exec docker://rocker/tidyverse:latest R
https://github.com/kevana/ui-for-docker. A quick start:
$ singularity exec docker://rocker/tidyverse:latest Rscript myScript.R
# Run:  <syntaxhighlight lang='bash'>
</syntaxhighlight>
docker run -d -p 9000:9000 --privileged \
    -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
</syntaxhighlight> where '''-v''' means to bind mount a volume.
# Open your browser to http://<dockerd host ip>:9000


== [https://github.com/scanon/shifter Shifter] ==
Note: Anyone in the local network can access the website without any authentication.


= [https://conda.io/docs/ Conda] =
== Rancher ==
* [https://hub.docker.com/r/continuumio/anaconda3 Getting started with Anaconda & Docker] using continuumio/anaconda3
* https://rancher.com/quick-start/. The doc above is not good enough to follow. Search Google for tutorial or get started guide including screenshots.
* [https://www.quora.com/What-is-the-difference-between-conda-and-Docker What is the difference between conda and Docker?]
* [https://www.howtoforge.com/tutorial/ubuntu-rancher-docker-container-manager/ How to Manage Docker Containers with Rancher on Ubuntu 16.04]
 
* [https://hackernoon.com/creating-a-scalable-application-using-docker-rancher-rancheros-cattle-5feb83a3e743 Creating A Scalable Application Using Docker + Rancher + RancherOs + Cattle]
== Bioconda ==
* Initial setup video https://youtu.be/1EMW1y7529Y
* https://bioconda.github.io/
* Training from Rancher Labs https://youtu.be/8K14A_CZFdI. It seems Rancher is complicated but powerful. The whole operation is like Amazon Cloud.
* https://anaconda.org/bioconda
* [https://gist.github.com/lmmendes/fbed32a452cf02d2a1095658795cb3d2 Running Rancher locally (with two hosts) using MacOS Docker and VirtualBox]
* https://www.biorxiv.org/content/early/2017/10/27/207092
* To allow UDP port
* https://zhuanlan.zhihu.com/p/25085567
<syntaxhighlight lang='bash'>
* [http://slides.com/olexschoen/snakemake-bioconda#/ Snakemake: Reproducible and scalable data analysis]
$ sudo apt-get install ufw
* https://chrisconlan.com/installing-r-python-anaconda-biologists/. Note that the R version is 3.4.2 but the latest one should be 3.4.3.
$ sudo ufw allow 4500/udp
$ sudo ufw allow 500/udp
</syntaxhighlight>
* discoposse.com
** [http://discoposse.com/2015/11/08/rancher-part-1-installing-rancher-and-setting-access-control/ Part 1] Installing Rancher and Setting Access Control
** [http://discoposse.com/2015/11/09/rancher-part-2-adding-a-docker-host-to-rancher/ Part 2] Adding a Docker Host to Rancher
** [http://discoposse.com/2015/11/12/rancher-part-3-adding-the-dockerhub-to-our-rancher-registry/ Part 3] Adding the DockerHub to our Rancher Registry
** [http://discoposse.com/2015/11/13/rancher-part-4-using-the-catalog-example-with-glusterfs/ Part 4] Using the Catalog Example with GlusterFS


Using docker to install conda (https://conda.io/docs/user-guide/tutorials/index.html)
== [https://github.com/tobegit3hub/seagull Seagull] ==
<syntaxhighlight lang='bash'>
https://youtu.be/TuT5gb8oRw8
$ docker run -t -i --name test --net=host ubuntu bash
# apt-get update
# apt-get install -y wget bzip2 python
# wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh
# wget https://repo.continuum.io/archive/Anaconda2-5.1.0-Linux-x86_64.sh
# bash Miniconda2-latest-Linux-x86_64.sh
# bash Anaconda2-5.1.0-Linux-x86_64.sh
# exit


$ docker start test
<pre>
$ docker exec -i -t test bash
docker run -d -p 127.0.0.1:10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull
# conda list  # WORKS!
</pre>
# conda config --add channels r
 
# conda config --add channels defaults
The only issue is there is no username/password to protect other people to access the web GUI. The solution of binding to localhost to restrict the access does not work for remote administration.
# conda config --add channels conda-forge
 
# conda config --add channels bioconda
That is, the tool is suitable for home use.
# conda install bwa  (Segmentation fault. Core dumped)
 
# which bwa
== [https://kitematic.com/ Kitematic] (Mac, Windows and Ubuntu) ==
/root/anaconda2/bin/bwa
Owned by Docker. Available for Mac OS X 10.8+ and Windows 7+ (64-bit) and Ubuntu. https://github.com/docker/kitematic/releases/
# conda install r  (Only get 3.4.2 but the latest is 3.4.3.)
# conda install bowtie
# bowtie --version
# conda install gatk (https://bioconda.github.io/recipes/gatk/README.html)
  (Due to license restrictions, this recipe cannot distribute and install GATK directly)
  (R is downgraded to 3.2.2:( )
  (Segmentation fault. Core dumped)
# exit
# docker stop test
# docker rm test
</syntaxhighlight>


Get miniconda image instead of using a Ubuntu image
Run containers through a simple, yet powerful graphical user interface.
<syntaxhighlight lang='bash'>
 
$ docker pull continuumio/miniconda
It can not connect to remote docker machines.
$ docker run -i -t continuumio/miniconda /bin/bash
# conda install r  (get 3.4.2)
# conda config --add channels bioconda
# conda install bwa  (OK, no error)
# conda install gatk  (R was downgraded to 3.2.2, install openjdk 8.0.121)
# which gatk
/opt/conda/bin/gatk
# gatk -h
GATK jar file not found. Have you run "gatk-register"?
</syntaxhighlight>
Issues:
* R version is not up to date
* '''So the problem is installing GATK requires an installation of R and the current R was affected.'''


= [https://coreos.com/ CoreOS] =
A [https://www.r-bloggers.com/share-your-shiny-apps-with-docker-and-kitematic/ Share your Shiny Apps with Docker and Kitematic!]
Redhat has acquired CoreOS 1/31/2018.


== Installation ==
== [https://github.com/shipyard/shipyard Shipyard] (retired) ==
* [https://coreos.com/os/docs/latest/quickstart.html Quick Start]
* [https://www.sumologic.com/blog/code/managing-containers-docker-shipyard/ Managing Containers with Docker Shipyard]
* [https://youtu.be/vy6hWsOuCh8  Installing CoreOS on a bare metal or virtual machine] from the user Format C: in youtube
* Three alternatives:
* [https://youtu.be/M0TYqVDnNAI Assigning Static IP to a CoreOS Server]
** [http://rancher.com/ Rancher]
* [https://www.youtube.com/watch?v=6LOiIH8s3xM Mounting storage in CoreOS]
** [https://github.com/kevana/ui-for-docker Docker UI]
* [https://www.youtube.com/watch?v=InLmXWgPzBs Installing, Deploying Docker containers with Fig / Docker Compose on boot2docker or CoreOS]
** [https://portainer.io/ Portainer]
* [https://www.youtube.com/watch?v=S9kfP2WYV_I Running a Private Docker Registry Container]


We first boot a liveCD from any OS (CentOS works but Ubuntu 16.04 gave errors). In Virtualbox, we choose 'Red Hat' if we use CentOS.  
== VS Code ==
* [https://youtu.be/i7ABlHngi1Q Docker For Beginners: From Docker Desktop to Deployment]
* [https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers Visual Studio Code Remote - Containers]
* [https://www.docker.com/blog/how-to-develop-inside-a-container-using-visual-studio-code-remote-containers/ How to Develop Inside a Container Using Visual Studio Code Remote Containers]
* [https://www.cloudsavvyit.com/12837/how-to-edit-code-in-docker-containers-with-visual-studio-code/ How to Edit Code in Docker Containers With Visual Studio Code]


Once the VM is created. We go to the settings. Create a bridged network or host-only network first (even we can get files from the host without creating a host-only network). Storage: choose CentOS-7.
= Applications =
[[Docker_Applications|Docker Applications]]


# Get the [https://coreos.com/os/docs/latest/installing-to-disk.html install script] from Github and create <'''coreos_install.sh'''> and chmod +x
== CasaOS ==
# create <'''cloud-config.yaml'''> file which will include ssh_authorized_keys generated from another machine. It should also contain a new token for the cluster from https://discovery.etcd.io/new.
Every app is based on a Docker application
# ls -l /dev/sd*
* https://casaos.io/
# run '''sudo ./coreos_install.sh -d /dev/sda -C stable -c cloud-config.yaml'''. It will download the latest stable CoreOS, install to the HD
** https://wiki.casaos.io/en/get-started. It also supports arm64, armv7.
# Don't leave the VM or it will freeze. Issue '''sudo shutdown -h now''' once we see the word 'Success' at the last line of the output.
** http://casaos.local
# Remove CentOS from the VM storage. Boot the coreOS VM.
** https://docs.zimaboard.com/docs/index.html Default login casaos/casaos. For a new user, the password has to be at least 5 characters.
* [https://youtu.be/FwJByjTdKks Revisiting CasaOS After A Few Months] 2022-6-14
* [https://youtu.be/w44CypRO5l4 Home Servers Have NEVER Been This Easy: CasaOS + ZimaBoard] 4/23/2023
* [https://github.com/xp1ode/new/blob/506bf428592a9604c4d8ca4cc6d0426280805b48/Screenshot%20from%202022-11-15%2006-12-55.png List of apps] 2022/11


The new screen shows ''corebm1 login'' with an IP. Go back to another machine and type '''ssh -i /tmp/CoreOSBM_rsa core@192.168.56.101'''. Inside CoreOS, we can type '''docker images'''.
= Orchestrator =
== [https://www.docker.com/kubernetes Kubernete] ==
* [https://www.zdnet.com/article/kubernetes-dropping-docker-is-not-that-big-of-a-deal/ Kubernetes dropping Docker is not that big of a deal]
* [https://www.freecodecamp.org/news/kubernetes-vs-docker-whats-the-difference-explained-with-examples/ Kubernetes VS Docker: What's the Difference? Explained With Examples]
* [https://kodekloud.com/p/kubernetes-for-the-absolute-beginners-hands-on Kubernetes For The Absolute Beginner - Hands On] from kodekloud.com
* [http://docker-k8s-lab.readthedocs.io/en/latest/ Docker Kubernetes Lab Handbook] by Peng Xiao. The github page is on https://github.com/xiaopeng163/docker-k8s-lab.
* [https://youtu.be/2G-A6Knjrvo Introducing Kubernetes] by Marc Sluiter. Kubenetes can be used to schedule, run and manage containers in a cluster of virtual or physical machines.
** Starting by Google in 2014
** Pods: smallest unit of deployment. small group of tightly coupled containers. share network and data volumes. routable IP address. multiple pods per node.
* [https://youtu.be/6xJwQgDnMFE Create a 2-node Kubernetes cluster in 10 minutes]
** [https://github.com/kubernetes/dashboard Kubernetes Dashboard]
* [https://youtu.be/_vHTaIJm9uY Kubernetes Webinar Series - Getting Started with Kubernetes]
** https://thenewstack.io/tutorial-configuring-ultimate-development-environment-kubernetes/
** https://github.com/janakiramm/Kubernetes-dev-env
* [https://www.oreilly.com/ideas/how-to-manage-docker-containers-in-kubernetes-with-java Deploying Java Applications with Docker and Kubernetes]
* [https://blog.alexellis.io/docker-for-mac-with-kubernetes/ First impressions: Docker for Mac with Kubernetes]
* [https://github.com/kubernetes/minikube Minikube]: run Kubernetes locally
** [https://www.howtoforge.com/tutorial/how-to-install-kubernetes-with-minikube-on-ubuntu-1804-lts/ How to Install Kubernetes with Minikube on Ubuntu 18.04 LTS]
** [https://opensource.com/article/19/12/kubernetes-namespaces Kubernetes namespaces for beginners]. You need to have Minikube, Helm, and the kubectl command line installed.
* [https://www.biorxiv.org/content/10.1101/488643v2?rss=1 Galaxy-Kubernetes integration: scaling bioinformatics workflows in the cloud] Moreno et al 2019
* [https://seandavi.github.io/2019/03/helm-on-google-kubernetes-engine/ Helm on Google Kubernetes Engine] by Sean Davis
* [https://microk8s.io/ MicroK8s]
** [https://github.com/CanonicalLtd/multipass Multipass]
** [https://itnext.io/microk8s-on-macos-98f1de3aa63e MicroK8s on MacOS]
* [https://www.howtoforge.com/resource-limits-in-kuberenetes/ Resource Limits in Kuberenetes]
* [https://github.com/seandavi/Orchestra?s=09 Orchestra] and [https://eurobioc2020.bioconductor.org/workshops?s=09 European Bioconductor Meeting 2020]
* [https://www.cloudsavvyit.com/9783/kubernetes-alternatives-to-docker-commands/ Kubernetes Alternatives to Docker Commands]
* [https://www.makeuseof.com/what-is-kubernetes/ What Is Kubernetes and What Is It Used For?]


The '''cloud-config.yaml'' file has to follow the format in https://coreos.com/os/docs/latest/cloud-config.html. Use the online validator https://coreos.com/validate/ to correct. At first I use the file from the youtube video. There is no error coming out when I ran the installation script. But I cannot connect to coreOS. The cloud-config.yaml file I use is (pay attention to '-', double quotes and indent characters)
== Kubernete vs Docker swarm ==
<pre>
* https://platform9.com/blog/kubernetes-docker-swarm-compared/
#cloud-config
* [https://www.ithome.com.tw/news/124290 DigitalOcean容器應用開發大調查:近半數開發者已採用]
#
 
# set hostname
== k3s: Lightweight Kubernetes ==
hostname: CoreBM1
[https://opensource.com/article/20/3/kubernetes-raspberry-pi-k3s Run Kubernetes on a Raspberry Pi with k3s]
 
== Kubeflow ==
* [https://www.kubeflow.org/ The Machine Learning Toolkit for Kubernetes]
 
= Other containers =
[https://freedium.cfd/https://codingplainenglish.medium.com/docker-is-dead-and-its-about-time-b457d14b0a72 Docker Is Dead — And It's About Time]


# Set ssh key
== Podman ==
ssh_authorized_keys:
<ul>
  - "ssh-rsa AAAAB3 ..... brb@T3600"
<li>[https://podman.io/docs/installation Podman Installation Instructions]
<ul>
<li> [https://ostechnix.com/install-podman-desktop-in-linux/ How To Install Podman Desktop In Linux]
<li> Raspberry Pi OS use the standard Debian's repositories, so it is fully compatible with Debian's arm64 repository. You can simply follow the steps for Debian to install Podman.
<li> I can install it on office computer (Mac), but running 'podman pull' will give me an error. Your network might be using an SSL inspection proxy that intercepts and re-signs SSL certificates. This proxy effectively becomes the "unknown authority" that signed the certificate. A simple solution is to change to '''wifi 'guest' ''' network instead of the corporate network.
{{Pre}}
$ podman machine init && podman machine start # create VM, needed on mac/Windows
$ podman pull hello-world
Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull quay.io/podman/hello:latest...
Error: internal error: unable to copy from source docker://quay.io/podman/hello:latest: initializing source docker://quay.io/podman/hello:latest: pinging container registry quay.io: Get "https://quay.io/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority


coreos:
$ podman machine stop
  etcd:
$ podman machine rm
    discovery: "https://discovery.etcd.io/d3e95 .... "
$ podman machine list
# sudo ./installos -d /dev/sda -C stable -c cloud-config.yaml
</pre>
</pre>
</ul>
<li>[https://linuxhandbook.com/docker-vs-podman/ Podman vs docker]:
* One of the main differences between Podman and Docker is their architecture. Docker uses a client-server architecture with a central daemon that manages containers. In contrast, Podman is daemonless and uses a fork-exec model to manage containers.
* '''Podman is designed to run containers without requiring root privileges or the use of sudo'''. This is one of the key differences between Podman and Docker, as Docker requires root privileges to run containers.
* Both Podman and Docker are compatible with the Open Container Initiative (OCI) container specification, which means that they can run the same container images. However, '''Podman is more closely aligned with Kubernetes''' and its native container runtime, while Docker also works with its own orchestration tool, Docker Swarm.
* Podman provides several '''benefits''' over Docker. For example, Podman is daemon-less, which means that if the Docker daemon crashes, the containers are in an uncertain state. This is prevented by making Podman daemon-less. You can also use systemd to manage your containers with Podman, which gives you virtually unlimited configurability compared to Docker. Hooking Podman with systemd allows you to update running containers with minimal downtime and recover from any bad updates.


== CoreOS exploration ==
<li>Podman is a project from Red Hat
<li>[https://www.howtogeek.com/devops/getting-started-with-podman-desktop-an-open-source-docker-desktop-alternative/ Getting Started With Podman Desktop, an Open Source Docker Desktop Alternative]
<li>[https://phoenixnap.com/kb/podman-compose Podman Compose - Managing Containers]
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
brb@T3600 /tmp $ ssh -i /tmp/id_rsa [email protected]
pip3 install podman-compose
Enter passphrase for key '/tmp/id_rsa':
</syntaxhighlight>
CoreOS stable (1010.6.0)
But it seems the compatibility is an issue even I tried a small example based on alpine image.
core@CoreBM1 ~ $
 
core@CoreBM1 ~ $ docker images
<li>Nginx example (works)
REPOSITORY          TAG                IMAGE ID            CREATED            SIZE
:<syntaxhighlight lang='bash'>
core@CoreBM1 ~ $ df -h
podman run -it --rm -d -p 8080:80 \
Filesystem      Size  Used Avail Use% Mounted on
  --name web \
devtmpfs        1.4G    0  1.4G  0% /dev
  -v /mnt/Podman/site-content:/usr/share/nginx/html \
tmpfs          1.4G    0  1.4G  0% /dev/shm
  docker.io/libary/nginx
tmpfs          1.4G  340K  1.4G  1% /run
</syntaxhighlight>
tmpfs          1.4G    0  1.4G  0% /sys/fs/cgroup
 
/dev/sda9        18G  23M  17G  1% /
<li>[https://developers.redhat.com/articles/2023/05/23/podman-desktop-now-generally-available Podman Desktop 1.0]: Local container development made easy.
/dev/sda3      985M  589M  345M  64% /usr
 
tmpfs          1.4G    0  1.4G  0% /media
<li>[https://dzone.com/articles/podman-for-docker-users Podman for Docker Users]
/dev/sda1      128M  37M  92M  29% /boot
* Prerequisites
tmpfs          1.4G    0  1.4G  0% /tmp
* Moving Images from Docker to Podman
/dev/sda6      108M  52K  99M  1% /usr/share/oem
* Creating a Basic Nuxt.js Project
core@CoreBM1 ~ $ free -m
* Building a Container Image for Your Nuxt.JS Project
             total      used      free    shared    buffers    cached
* Push Your Podman Image to Quay.io
Mem:          2713        187      2525          0          9        109
* '''Run Your Podman Image with Docker'''
-/+ buffers/cache:        68      2644
* Creating Pods
Swap:            0          0          0
* Generate a Kubernetes Pod Spec with Podman
core@CoreBM1 ~ $ lsb_release -a
* Create a Kubernetes Cluster with Kind (Optional)
-bash: lsb_release: command not found
* Deploying to Kubernetes
core@CoreBM1 ~ $ docker pull ubuntu
<li>Podman, Docker and Singularity all support OCI container format images.
Using default tag: latest
<li>[https://appsilon.com/docker-vs-podman-vs-singularity/ Docker vs. Podman vs. Singularity: Which Containerization Platform is Best for R Shiny?]
latest: Pulling from library/ubuntu
 
f069f1d21059: Pull complete
<li>[https://codesmash.dev/why-i-ditched-docker-for-podman-and-you-should-too Why I Ditched Docker for Podman]
ecbeec5633cf: Pull complete
</ul>
ea6f18256d63: Pull complete
 
54bde7b02897: Pull complete
=== Use docker images ===
Digest: sha256:bbfd93a02a8487edb60f20316ebc966ddc7aa123c2e609185450b96971020097
How do I do "docker run --rm --name rshiny -p 81:3838 rocker/shiny" using podman?
Status: Downloaded newer image for ubuntu:latest
 
core@CoreBM1 ~ $ docker images
Docker and Podman use completely separate storage systmes:
REPOSITORY          TAG                IMAGE ID            CREATED            SIZE
* Docker uses /var/lib/docker
ubuntu              latest              0f192147631d        7 days ago          132.7 MB
* Podman uses /var/lib/containers (or ~/.local/share/containers for rootless)
core@CoreBM1 ~ $
 
</syntaxhighlight>
Tip: Export from Docker, import to Podman
<syntaxhighlight lang='sh'>
docker save rocker/shiny:4.4.0 | podman load
# Or
# docker save rocker/shiny:4.4.0 | gzip > rocker_shiny.tar.gz
# podman load < rocker_shiny.tar.gz
# rm rocker_shiny.tar.gz
 
podman images
 
podman run --rm --name rshiny -p 3838:3838 rocker/shiny:4.4.0
 
podman rmi docker.io/rocker/shiny:4.4.0
</syntaxhighlight>
 
== [https://sylabs.io/ Singularity] and HPC systems ==
* Old URL at [http://singularity.lbl.gov/ singularity.lbl.gov]
* Singularity enables users to have full control of their environment; Singularity containers let users run applications in a Linux environment of their choosing. No 'sudo' is needed in general unless you want to build a container from a recipe.
* Containers are more like an executable file for you to use
* Containers are stored under the current location. It does not have a centre location (like /etc/default/docker if we use docker) to store images.
* Can convert Docker containers to Singularity and run containers directly from Docker Hub
* These bind points cannot be created unless the path already exists within the container. To ensure access to these storage spaces and remedy bind point errors, create these directories in the %post section of your Bootstrap file.
* [https://singularity-hub.org/ Singularity Hub]
 
Ref:
* [https://hpc.nih.gov/apps/singularity.html Singularity] at NIH/Biowulf. It needs to run 'module load singularity' first to load related commands.
* NIH-HPC
** [https://singularity-tutorial.github.io/ Tutorial] and its [https://github.com/NIH-HPC/Singularity-Tutorial Github] source ('''valuable''')
** [https://github.com/nih-byob/presentations/tree/master/2019/01_bioinformatics_tips Bioinformatics advice I wish I learned 10 years ago]
** [https://github.com/NIH-HPC/singularity-def-files NIH HPC Singularity Definition Files]
* [https://tin6150.github.io/psg/blogger_container_hpc.html DOCKER VS SINGULARITY VS SHIFTER VS UGE CONTAINER EDITION]
* [https://github.com/data61/gossamer xenome] case where the build instruction is good for Ubuntu 16.04. If we try to build under Ubuntu 14.04 (tested using docker run), we will get an error message '' CMake 3.1 or higher is required.  You are running version 2.8.12.2''.
* https://github.com/NIH-HPC/singularity-examples/blob/master/rnaseq/Singularity.rnaseq
 
'''Comparison of docker and singularity commands:'''
{| class="wikitable"
|-
! [https://docs.docker.com/edge/engine/reference/commandline/docker/ docker] !! [http://singularity.lbl.gov/user-guide singularity]
|-
| $ docker pull ubuntu:latest <br/>$ docker pull broadinstitute/gatk3:3.8-0 || $ singularity pull docker://ubuntu:latest<br/>$ singularity pull docker://broadinstitute/gatk3:3.8-0
|-
| $ docker build -t myname/myapp:latest -f Dockerfile || $ singularity build myapp.sif myapp.def
|-
| $ docker shell (not exist) || $ singularity shell docker://broadinstitute/gatk3-3.8-0<br/>  $ singularity shell gatk3-3.8-0.img<br/> > ls  # the default location depends on the host system<br/>
> ls /usr  # this is from the container <br/><br/>$ singularity shell --bind ~/Downloads:/mnt XXX.img<br/>$ singularity shell docker://ubuntu:latest<br/># container is ephemeral
|-
| $ docker run --name test -it ubuntu date <br/><br/># <span style="color: red">The next example is similar to 'singularity exec'</span><br/>$ docker run --rm -i -t \<br/>  -v $(pwd):/usr/my_data \<br/>  broadinstitute/gatk3:3.8-0 \<br/>  bash /usr/my_data/myscript.sh || $ singularity run gatk3-3.8-0.img date
|-
| $ docker run --name ubuntu_bash --rm -i -t ubuntu bash<br/>$ docker exec -d ubuntu_bash touch /tmp/execWorks || # <span style="color: red">Most useful</span><br>$ singularity exec gatk3-3.8-0.img java -version <br/>$ singularity exec xxx.img cat /etc/*release<br>$ singularity exec docker://rocker/tidyverse:latest R <br/>$ singularity exec docker://rocker/tidyverse:latest Rscript myScript.R<br/>
|}
 
=== Cache ===
When we run ''singularity exec docker://rocker/tidyverse:latest R'', it will save something in the cache in our system.
 
It seems to be OK after I manually delete the directory $HOME/.singularity (tested in Biowulf).
 
=== RStudio ===
* [https://rviews.rstudio.com/2017/03/29/r-and-singularity/ R and Singularity] by Bryan Lewis
* [https://archive.sylabs.io/2018/10/rstudio-ide-and-server/ RStudio – IDE and Server powered by Singularity] by Jason Stover
* https://github.com/nickjer/singularity-rstudio and https://github.com/nickjer/singularity-r
* https://www.rocker-project.org/use/singularity/. It also includes how to run a SLURM job script.
* https://njstem.wordpress.com/2018/08/02/r-script-seurat-with-a-singularity-container-using-slurm/
* https://journal.r-project.org/archive/2017/RJ-2017-065/RJ-2017-065.pdf
 
<syntaxhighlight lang='bash'>
$ singularity exec docker://rocker/tidyverse:latest R
$ singularity exec docker://rocker/tidyverse:latest Rscript myScript.R
</syntaxhighlight>
 
== [https://github.com/scanon/shifter Shifter] ==
 
= [https://conda.io/docs/ Conda] =
* [https://www.quora.com/What-is-the-difference-between-conda-and-Docker What is the difference between conda and Docker?]
 
== Anaconda ==
* [https://hub.docker.com/r/continuumio/anaconda3 Getting started with Anaconda & Docker] using continuumio/anaconda3
 
== Bioconda ==
* https://bioconda.github.io/
* https://anaconda.org/bioconda
* https://www.biorxiv.org/content/early/2017/10/27/207092
* https://zhuanlan.zhihu.com/p/25085567
* [http://slides.com/olexschoen/snakemake-bioconda#/ Snakemake: Reproducible and scalable data analysis]
* https://chrisconlan.com/installing-r-python-anaconda-biologists/. Note that the R version is 3.4.2 but the latest one should be 3.4.3.
* [https://davetang.github.io/reproducible_bioinformatics/conda.html Introduction to Conda] Dave Tang
 
Using docker to install conda (https://conda.io/docs/user-guide/tutorials/index.html)
<syntaxhighlight lang='bash'>
$ docker run -t -i --name test --net=host ubuntu bash
# apt-get update
# apt-get install -y wget bzip2 python
# wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh
# wget https://repo.continuum.io/archive/Anaconda2-5.1.0-Linux-x86_64.sh
# bash Miniconda2-latest-Linux-x86_64.sh
# bash Anaconda2-5.1.0-Linux-x86_64.sh
# exit
 
$ docker start test
$ docker exec -i -t test bash
# conda list  # WORKS!
# conda config --add channels r
# conda config --add channels defaults
# conda config --add channels conda-forge
# conda config --add channels bioconda
# conda install bwa  (Segmentation fault. Core dumped)
# which bwa
/root/anaconda2/bin/bwa
# conda install r  (Only get 3.4.2 but the latest is 3.4.3.)
# conda install bowtie
# bowtie --version
# conda install gatk (https://bioconda.github.io/recipes/gatk/README.html)
  (Due to license restrictions, this recipe cannot distribute and install GATK directly)
  (R is downgraded to 3.2.2:( )
  (Segmentation fault. Core dumped)
# exit
# docker stop test
# docker rm test
</syntaxhighlight>
 
Get miniconda image instead of using a Ubuntu image
<syntaxhighlight lang='bash'>
$ docker pull continuumio/miniconda
$ docker run -i -t continuumio/miniconda /bin/bash
# conda install r  (get 3.4.2)
# conda config --add channels bioconda
# conda install bwa  (OK, no error)
# conda install gatk  (R was downgraded to 3.2.2, install openjdk 8.0.121)
# which gatk
/opt/conda/bin/gatk
# gatk -h
GATK jar file not found. Have you run "gatk-register"?
</syntaxhighlight>
Issues:
* R version is not up to date
* '''So the problem is installing GATK requires an installation of R and the current R was affected.'''
 
= [https://coreos.com/ CoreOS] =
* Redhat has acquired CoreOS 1/31/2018.
* [https://coreos.com/os/eol/ End-of-life announcement for CoreOS Container Linux]
 
== Installation ==
* [https://coreos.com/os/docs/latest/quickstart.html Quick Start]
* [https://youtu.be/vy6hWsOuCh8  Installing CoreOS on a bare metal or virtual machine] from the user Format C: in youtube
* [https://youtu.be/M0TYqVDnNAI Assigning Static IP to a CoreOS Server]
* [https://www.youtube.com/watch?v=6LOiIH8s3xM Mounting storage in CoreOS]
* [https://www.youtube.com/watch?v=InLmXWgPzBs Installing, Deploying Docker containers with Fig / Docker Compose on boot2docker or CoreOS]
* [https://www.youtube.com/watch?v=S9kfP2WYV_I Running a Private Docker Registry Container]
 
We first boot a liveCD from any OS (CentOS works but Ubuntu 16.04 gave errors). In Virtualbox, we choose 'Red Hat' if we use CentOS.
 
Once the VM is created. We go to the settings. Create a bridged network or host-only network first (even we can get files from the host without creating a host-only network). Storage: choose CentOS-7.
 
# Get the [https://coreos.com/os/docs/latest/installing-to-disk.html install script] from Github and create <'''coreos_install.sh'''> and chmod +x
# create <'''cloud-config.yaml'''> file which will include ssh_authorized_keys generated from another machine. It should also contain a new token for the cluster from https://discovery.etcd.io/new.
# ls -l /dev/sd*
# run '''sudo ./coreos_install.sh -d /dev/sda -C stable -c cloud-config.yaml'''. It will download the latest stable CoreOS, install to the HD
# Don't leave the VM or it will freeze. Issue '''sudo shutdown -h now''' once we see the word 'Success' at the last line of the output.
# Remove CentOS from the VM storage. Boot the coreOS VM.
 
The new screen shows ''corebm1 login'' with an IP. Go back to another machine and type '''ssh -i /tmp/CoreOSBM_rsa [email protected]'''. Inside CoreOS, we can type '''docker images'''.
 
The '''cloud-config.yaml'' file has to follow the format in https://coreos.com/os/docs/latest/cloud-config.html. Use the online validator https://coreos.com/validate/ to correct. At first I use the file from the youtube video. There is no error coming out when I ran the installation script. But I cannot connect to coreOS. The cloud-config.yaml file I use is (pay attention to '-', double quotes and indent characters)
<pre>
#cloud-config
#
# set hostname
hostname: CoreBM1
 
# Set ssh key
ssh_authorized_keys:
  - "ssh-rsa AAAAB3 ..... brb@T3600"
 
coreos:
  etcd:
    discovery: "https://discovery.etcd.io/d3e95 .... "
# sudo ./installos -d /dev/sda -C stable -c cloud-config.yaml
</pre>
 
== CoreOS exploration ==
<syntaxhighlight lang='bash'>
brb@T3600 /tmp $ ssh -i /tmp/id_rsa [email protected]
Enter passphrase for key '/tmp/id_rsa':
CoreOS stable (1010.6.0)
core@CoreBM1 ~ $
core@CoreBM1 ~ $ docker images
REPOSITORY          TAG                IMAGE ID            CREATED            SIZE
core@CoreBM1 ~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        1.4G    0  1.4G  0% /dev
tmpfs          1.4G    0  1.4G  0% /dev/shm
tmpfs          1.4G  340K  1.4G  1% /run
tmpfs          1.4G    0  1.4G  0% /sys/fs/cgroup
/dev/sda9        18G  23M  17G  1% /
/dev/sda3      985M  589M  345M  64% /usr
tmpfs          1.4G    0  1.4G  0% /media
/dev/sda1      128M  37M  92M  29% /boot
tmpfs          1.4G    0  1.4G  0% /tmp
/dev/sda6      108M  52K  99M  1% /usr/share/oem
core@CoreBM1 ~ $ free -m
             total      used      free    shared    buffers    cached
Mem:          2713        187      2525          0          9        109
-/+ buffers/cache:        68      2644
Swap:            0          0          0
core@CoreBM1 ~ $ lsb_release -a
-bash: lsb_release: command not found
core@CoreBM1 ~ $ docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
f069f1d21059: Pull complete
ecbeec5633cf: Pull complete
ea6f18256d63: Pull complete
54bde7b02897: Pull complete
Digest: sha256:bbfd93a02a8487edb60f20316ebc966ddc7aa123c2e609185450b96971020097
Status: Downloaded newer image for ubuntu:latest
core@CoreBM1 ~ $ docker images
REPOSITORY          TAG                IMAGE ID            CREATED            SIZE
ubuntu              latest              0f192147631d        7 days ago          132.7 MB
core@CoreBM1 ~ $
</syntaxhighlight>


== CoreOS cluster discovery ==
== CoreOS cluster discovery ==
https://coreos.com/os/docs/latest/cluster-discovery.html
https://coreos.com/os/docs/latest/cluster-discovery.html
 
 
== etcd ==
== etcd ==
* https://coreos.com/etcd/
* https://coreos.com/etcd/
 
 
== fleet ==
== fleet ==
* https://coreos.com/using-coreos/clustering/
* https://coreos.com/using-coreos/clustering/
 
 
= Resource =
= TryGhost =
== Internet ==
https://github.com/TryGhost/Ghost
* [https://opensource.com/article/19/11/microservices-cheat-sheet A guide to open source for microservices] from opensource.com
 
* [https://github.com/rainsworth/osip2019-containerisation-workshop/ Reproducible Research through Containerisation: Docker and Singularity] from rainsworth.
= Firecracker =
 
[https://jvns.ca/blog/2021/01/23/firecracker--start-a-vm-in-less-than-a-second/ Firecracker: start a VM in less than a second]
== Books ==
 
* The Docker Book: Containerization is the new virtualization
= Self-hosting =
* Orchestrating Docker  
[https://www.reddit.com/r/selfhosted/comments/uvq1x3/tools_and_resources_for_selfhosting/ Tools and Resources for Self-Hosting]
* Docker Hands on: Deploy, Administer Docker Platform
 
* [https://www.oreilly.com/library/view/learn-docker-/9781788997027/?afsrc=1 Learn Docker - Fundamentals of Docker] 18.x by Gabriel N. Schenker. Release Date: April 2018. https://github.com/fundamentalsofdocker/labs
= Linux in browser =
* [https://www.amazon.com/Docker-Deep-Dive-Nigel-Poulton/dp/1521822808 Docker Deep Dive] by by Nigel Poulton. 2017  
<ul>
* Master Docker (2nd, 2017) by Russ McKendrick, Scott Gallagher. Source code on [https://github.com/PacktPublishing/Mastering-Docker-Second-Edition github].
<li>Webtop, https://hub.docker.com/r/linuxserver/webtop#!
 
* [[#Play_with_Docker_.28PWD.29|Play with Docker]]
== Blogs ==
* [https://www.linuxserver.io/blog/2021-05-05-meet-webtops-a-linux-desktop-environment-in-your-browser Meet Webtops A Linux Desktop Environment In Your Browser]
* http://blog.thoward37.me/articles/where-are-docker-images-stored/
* [https://shownotes.opensourceisawesome.com/webtops/ Webtops - Linux Desktops in Docker]
* [http://www.ithome.com.tw/people/109065 Docker容器架構最大儲存挑戰是,你根本不知道資料存在何處]
<pre>
* [https://blog.quickmediasolutions.com/2017/08/23/running-everything-in-docker.html Running Everything in Docker]. Docker Compose was used. Several applications were illustrated: mediawiki, Jenkins, Gogs & caddy-docker.
---
version: "2.1"
services:
  webtop:
    image: lscr.io/linuxserver/webtop:ubuntu-mate
    container_name: webtop
    security_opt:
      - seccomp:unconfined #optional
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Chicago
      - SUBFOLDER=/ #optional
      - KEYBOARD=en-us-qwerty #optional
      - TITLE=Webtop #optional
    volumes:
      - ./data:/config
      - /var/run/docker.sock:/var/run/docker.sock #optional
    ports:
      - 3000:3000
    devices:
      - /dev/dri:/dev/dri #optional
    shm_size: "1gb" #optional
    restart: unless-stopped
</pre>
<pre>
$ nano docker-compose.yml
$ docker-compose up -d
$ ls data # files in this directory will be shared between the container and the host
# Open http://localhost:3000
</pre>
If we remove 'ubuntu-mate', it will create alpine linux instead.
 
In the alpine linux ([https://www.tecmint.com/apk-command-examples/ 13 Apk Commands for Alpine Linux Package Management]), we can use the following commands to install a package. However, meld is not responding from my testing in the setup.
<pre>
sudo apk update
sudo apk add meld nano htop neofetch
</pre>
</li>
<li>[https://www.kasmweb.com/ Kasm Workspaces], https://hub.docker.com/r/kasmweb/desktop/#!
* [https://youtu.be/go7n0FmNqh4 KASM: Isolated Disposable Remote Workspace Via Your Browser] (video)
* [https://www.youtube.com/watch?v=hXkZVqqAg7c Kasm Workspaces: Your Solution for Remote Desktops?] (video)
* [https://youtu.be/_ur59HHoRGc?t=442 Desktop Apps in Docker Containers with Kasm Workspaces] (you cannot install any software there)
</li>
</ul>
 
= Resource =
== Internet ==
* [https://opensource.com/article/19/11/microservices-cheat-sheet A guide to open source for microservices] from opensource.com
* [https://github.com/rainsworth/osip2019-containerisation-workshop/ Reproducible Research through Containerisation: Docker and Singularity] from rainsworth.
* [https://youtu.be/fqMOX6JJhGo Docker Tutorial for Beginners - A Full DevOps Course on How to Run Applications in Containers] from freeCodeCamp.org
* [https://www.howtogeek.com/733522/docker-for-beginners-everything-you-need-to-know/ Docker for Beginners: Everything You Need to Know]
 
== Books ==
* The Docker Book: Containerization is the new virtualization
* Orchestrating Docker  
* Docker Hands on: Deploy, Administer Docker Platform
* [https://www.oreilly.com/library/view/learn-docker-/9781788997027/?afsrc=1 Learn Docker - Fundamentals of Docker] 18.x by Gabriel N. Schenker. Release Date: April 2018. https://github.com/fundamentalsofdocker/labs
* [https://www.amazon.com/Docker-Deep-Dive-Nigel-Poulton/dp/1521822808 Docker Deep Dive] by by Nigel Poulton. 2017  
* Master Docker (2nd, 2017) by Russ McKendrick, Scott Gallagher. Source code on [https://github.com/PacktPublishing/Mastering-Docker-Second-Edition github].
 
== Blogs ==
* collabnix
** [https://dockerlabs.collabnix.com/ Welcome to Docker Labs]
** [https://dockerlabs.collabnix.com/intermediate/workshop/ Docker Workshop for Intermediate Users]
* http://blog.thoward37.me/articles/where-are-docker-images-stored/
* [http://www.ithome.com.tw/people/109065 Docker容器架構最大儲存挑戰是,你根本不知道資料存在何處]
* [https://blog.quickmediasolutions.com/2017/08/23/running-everything-in-docker.html Running Everything in Docker]. Docker Compose was used. Several applications were illustrated: mediawiki, Jenkins, Gogs & caddy-docker.
 
== Tips/trouble shooting ==
* [https://nickjanetakis.com/blog/docker-tip-64-dealing-with-unexplained-docker-errors Dealing with Unexplained Docker Errors] and other [https://nickjanetakis.com/blog/tag/docker-tips-tricks-and-tutorials tips and tricks]
* [https://medium.com/lucjuggery/running-a-container-with-a-non-root-user-e35830d1f42a Running a container with a non root user]
* [https://stackoverflow.com/a/49941240 Error: Cannot start container: port has already been allocated]. '''sudo service docker restart'''
 
== Play with Docker (PWD) ==
* http://labs.play-with-docker.com/
* http://training.play-with-docker.com/, [https://training.play-with-docker.com/alacart/ A full list of labs]
* https://blog.docker.com/2017/07/best-way-learn-docker-free-play-docker-pwd/
* One session is 4 hours. Each session can have multiple instance. Each instance will be allocated 4GB mem. Each docker image is stored in memory.
* '''df -h''' shows there is only 4.7G space for /var/lib/docker directory
* It is based on Alpine Linux. To install htop, do '''apk add htop'''. But '''htop''' command shows the resource from the host, not from the user's account.
* '''ctrl + insert''' to copy and '''shift + insert''' to paste
* [https://github.com/play-with-docker/play-with-docker/issues/238 connect to a play-with-docker instance]. Answer: You just need to create a random private key. [https://kostislab.blogspot.com/2019/03/play-with-play-with-docker-form-your.html Play with "Play with Docker" from your terminal!].


== Tips/trouble shooting ==
* Some applications I've tested.
* [https://nickjanetakis.com/blog/docker-tip-64-dealing-with-unexplained-docker-errors Dealing with Unexplained Docker Errors] and other [https://nickjanetakis.com/blog/tag/docker-tips-tricks-and-tutorials tips and tricks]
** webtop (OK)
* [https://medium.com/lucjuggery/running-a-container-with-a-non-root-user-e35830d1f42a Running a container with a non root user]
** r-base:3.6.3, r-base:4.1.0, r-base:4.1.1 (OK)
** r-base:4.1.2, r-base:4.2.0 (ERROR: R_HOME ('/usr/lib/R') not found). Maybe the docker version there is too old.


== Play with Docker (PWD) ==
== Alternatives ==
* http://labs.play-with-docker.com/
[https://www.makeuseof.com/best-docker-alternatives/ The 9 Best Docker Alternatives for Container Management]
* http://training.play-with-docker.com/, [https://training.play-with-docker.com/alacart/ A full list of labs]
* https://blog.docker.com/2017/07/best-way-learn-docker-free-play-docker-pwd/


== Serverless computing ==
== Serverless computing ==

Latest revision as of 19:47, 27 November 2025

Official web page http://docker.io.

Docker is both a client and a server: the server is a daemon that runs on Linux. The normal approach was that you used docker on the same server the daemon was running on - however it was possible to connect the docker client to a remote docker daemon.

Installation

Which OS to install?

Containers vs virtual machines

KubeVirt

OS containers vs application containers

Differences:

  • OS containers: LXC, OpenVZ, Linux VServer, BSD Jails and Solaris zones. The container acts as VPS.
  • App containers: Docker, Rocket. The container acts as an application.

Current release version

Ubuntu x86 and Mint

One-line script

https://github.com/docker/docker-install, https://docs.docker.com/engine/install/ubuntu/, https://twitter.com/portainerio/status/1650171336864550912

Note that 1) the one-liner is a huge security issue. 2) but how will you add the current user to docker group and then logout and log back in. 3) Linux Mint does not work.

$ curl -fsSL https://get.docker.com | bash
...
Client: Docker Engine - Community
 Version:           24.0.7
 API version:       1.43
 Go version:        go1.20.10
 Git commit:        afdd53b
 Built:             Thu Oct 26 09:08:17 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.7
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.10
  Git commit:       311b9ff
  Built:            Thu Oct 26 09:08:17 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.26
  GitCommit:        3dd1e886e55dd695541fdcd67420c2888645a495
 runc:
  Version:          1.1.10
  GitCommit:        v1.1.10-0-g18a0cb0
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

---------------

To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:

    dockerd-rootless-setuptool.sh install

Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.


To run the Docker daemon as a fully privileged service, but granting non-root
users access, refer to https://docs.docker.com/go/daemon-access/

WARNING: Access to the remote API on a privileged Docker daemon is equivalent
         to root access on the host. Refer to the 'Docker daemon attack surface'
         documentation for details: https://docs.docker.com/go/attack-surface/

--------------
$ # sudo groupadd docker
$ sudo usermod -aG docker $USER; newgrp docker

$ docker run hello-world

The newgrp docker command in Linux is used to switch the current user’s group ID during a login session. Specifically, it changes the user’s primary group to the docker group without logging out and back in. This is particularly useful when you need to gain the permissions associated with the docker group to run Docker commands.

$ id -gn
docker

Docker Desktop

Diet Pi

dietpi-software

  • Way 1: choose "Docker" but not "Docker Compose". Then I need to run the following too
    sudo apt install docker-compose-plugin
    
  • Way 2: Choose both "Docker Compose" and "Docker"

Manjaro Linux

Manjaro Linux Docker installation

sudo pacman -Syu
sudo pacman -S docker
sudo systemctl start docker.service
sudo systemctl enable docker.service
sudo docker version
sudo usermod -aG docker $USER
sudo reboot

docker search r-base

Without sudo, Post-installation

To use docker without sudo, follow the instruction on the official guide.

# Add the docker group if it doesn't already exist.
# sudo groupadd docker

# Add your user to the docker group.
sudo usermod -aG docker $USER

# Log out and log in

After running this command, you need to log out and log back in for the changes to take effect. This is because group membership is determined at login time. When you log in, the system reads the group membership information and assigns the appropriate permissions to your user account.

Upgrade Docker Desktop

It seems it does not affect running containers (e.g. RStudio on Mac).

Is it fine to upgrade Docker-ce while a container is running?

Doesn't matter. Your system will stop the container if you update docker.

Is there a way to hibernate a docker container

Live restore

Rate limits for GitHub Apps

Rate limits for GitHub Apps

When I tried several times of docker build, I finally got a message

Downloading GitHub repo XXX/XXXXX@HEAD
Error: Failed to install 'unknown package' from GitHub:
  HTTP error 403.
  API rate limit exceeded for XXX.XX.XXX.X. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)

  Rate limit remaining: 0/60
  Rate limit reset at: 2021-04-12 20:32:28 UTC

  To increase your GitHub API rate limit
  - Use `usethis::browse_github_pat()` to create a Personal Access Token.
  - Use `usethis::edit_r_environ()` and add the token as `GITHUB_PAT`.
Execution halted

CentOS

Boot2Docker

For Windows and OS operation systems, we have to use Boot2Docker. Boot2Docker is a local virtual machine with its own network interface and IP address. To find the Boot2Docker IP address you can check the value of the DOCKER_HOST environment variable. You're be prompted to set this variable when you start or install Boot2Docker the first time. You can find the IP address by running boot2docker ip command.

Note that since Windows and OS X don't share a file system as Linux, the command 'docker run' with '-v' flag to mount a local directory into a Docker container will not work with Boot2Docker release prior to 1.3. The support for volumes is now available for OS X but is not yet present for Windows with the release of Boot2Docker 1.3.

Windows

Note many of the information here have not been updated.

Docker can be run on Windows 10 Pro as a native application; see

The information below is based on running Docker on Windows 7.1 and 8. Your processor needs to support hardware virtualization.

  • Windows Installer includes msys-git, Virtualbox, Boot2Docker-cli management tool and Boot2Docker ISO.
  • Installation instruction for Windows OS. It will install Boot2Docker management tool with the boot2docker iso (based on Tiny Core Linux), Virtualbox and MYSYS-git UNIX tools.
  • Docker needs Admin right to be installed. However, Virtualbox can be installed by user's account.
  • If the installer detects a version of VirtualBox installed, the VirtualBox checkbox will not be checked by default (Windows OS). The VirtualBox cannot be used anymore after updating my VB from 4.3.18 to 4.3.20. The error may be related to Windows update according to Virtualbox forum.
Error in supR3HardenedWinReSpawn
  • Note that boot2docker cannot be installed/run inside a Windows guest machine. See this post and my Virtualbox wiki here. If we try to launch boot2docker-vm from Virtualbox, we will see a message "This kernel requires an x86-64 CPU, but only detected an i686 CPU."
  • After I switch back to an old version of virtualbox, every thing works again. I can even install Docker successfully.
    • Boot2Docker Start icon cannot be run directly because Notepad++ will automatically open it. A possible solution is to go to control panel and change default program for .sh file from Notepad++ to C:\Program Files (x86)\Git\bin\bash.exe.
    • The above step does not work well since a terminal appears and disappears quickly.
    • A working approach is to open Git Bash from Start menu. And run /c/Program Files/Boot2DockerforWindows/start.sh (or boot2docker start or boot2docer init)
    • A new VM called 'boot2docker-vm' will be created (we can open VirtualBox Manager to check). But I got an error error in run: Failed to start machine "boot2docker-vm" (run again with -v for details). The VM has an error on Network>Adapter2>VirtualBox Host-Only Ethernet Adapter #2. So I open the setting of <boot2docker-vm>, go to Network > Adapter 2 and change the dropdown list of Name from VirtualBox Host-Only Ethernet Adapter #2 to VirtualBox Host-Only Ethernet Adapter.
    • Now it works either I directly click boot2docker-vm VM from VB Manager or use the command start.sh from Git Bash.

$ # boot2docker is in the PATH variable, so there is not need to cd to the folder.
$ boot2docker start
initializing...
Virtual machine boot2docker-vm already exists

starting...
Waiting for VM and Docker daemon to start...
........o
Started.
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\ca.pem
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\cert.pem
Writing c:\Users\brb\.boot2docker\certs\boot2docker-vm\key.pem
Docker client does not run on Windows for now. Please use
    "c:\Program files\Boot2Docker for Windows\boot2docker.exe" ssh
to SSH into the VM instead.


192.168.56.101
connecting...
                        ##        .
                  ## ## ##       ==
               ## ## ## ##      ===
           /""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
           \______ o          __/
             \    \        __/
              \____\______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.4.1, build master : 86f7ec8 - Tue Dec 16 23:11:29 UTC 2014

Docker version 1.4.1, build 5bc2ff8
docker@boot2docker:~$ docker
Usage: docker [OPTIONS] COMMAND [arg...]

A self-sufficient runtime for linux containers.

Options:
  --api-enable-cors=false                      Enable CORS headers in the remote
 API
  -b, --bridge=""                              Attach containers to a pre-existi
ng network bridge
...
Run 'docker COMMAND --help' for more information on a command.
docker@boot2docker:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
hello-world:latest: The image you are pulling has been verified
511136ea3c5a: Pull complete
31cbccb51277: Pull complete
e45a5af57b00: Pull complete
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

For more examples and ideas, visit:
 http://docs.docker.com/userguide/

docker@boot2docker:~$ ls
boot2docker, please format-me
docker@boot2docker:~$ pwd
/home/docker
docker@boot2docker:~$ ls /
bin/     dev/     home/    lib/     mnt/     proc/    run/     sys/     usr/
c/       etc/     init     linuxrc  opt/     root/    sbin/    tmp      var/

docker@boot2docker:~$ docker run hello-world
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

For more examples and ideas, visit:
 http://docs.docker.com/userguide/
docker@boot2docker:~$
docker@boot2docker:~$
docker@boot2docker:~$
docker@boot2docker:~$ docker run -it ubuntu bash
Unable to find image 'ubuntu:latest' locally
ubuntu:latest: The image you are pulling has been verified
53f858aaaf03: Pull complete
837339b91538: Pull complete
615c102e2290: Pull complete
b39b81afc8ca: Pull complete
511136ea3c5a: Already exists
Status: Downloaded newer image for ubuntu:latest


root@ea7e3289a01a:/# pwd
/
root@ea7e3289a01a:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs           19G  269M   17G   2% /
none             19G  269M   17G   2% /
tmpfs          1005M     0 1005M   0% /dev
shm              64M     0   64M   0% /dev/shm
/dev/sda1        19G  269M   17G   2% /etc/hosts
tmpfs          1005M     0 1005M   0% /proc/kcore
root@ea7e3289a01a:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
root@ea7e3289a01a:/# exit
exit


docker@boot2docker:~$ pwd
/home/docker
docker@boot2docker:~$ ls
boot2docker, please format-me
docker@boot2docker:~$ exit
[Press any key to exit]

brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
$ boot2docker down

brb@NCI-01825357 /c/Program files/Boot2Docker for Windows
$
$ boot2docker --help
Usage: c:\Program files\Boot2Docker for Windows\boot2docker.exe [<options>] <command> [<args>]

Boot2Docker management utility.

Commands:
   init                Create a new Boot2Docker VM.
   up|start|boot       Start VM from any states.
   ssh [ssh-command]   Login to VM via SSH.
   save|suspend        Suspend VM and save state to disk.
   down|stop|halt      Gracefully shutdown the VM.
   restart             Gracefully reboot the VM.
   poweroff            Forcefully power off the VM (may corrupt disk image).
   reset               Forcefully power cycle the VM (may corrupt disk image).
   delete|destroy      Delete Boot2Docker VM and its disk image.
   config|cfg          Show selected profile file settings.
   info                Display detailed information of VM.
   ip                  Display the IP address of the VM's Host-only network.
   shellinit           Display the shell commands to set up the Docker client.
   status              Display current state of VM.
   download            Download Boot2Docker ISO image.
   upgrade             Upgrade the Boot2Docker ISO image (restart if running).
   version             Display version information.

Options:
      --basevmdk="": Path to VMDK to use as base for persistent partition
      --clobber=false: overwrite Docker client binary on boot2docker upgrade
      --dhcp=true: enable VirtualBox host-only network DHCP.
      --dhcpip=192.168.59.99: VirtualBox host-only network DHCP server address.
....
  -v, --verbose=false: display verbose command invocations.
      --vm="boot2docker-vm": virtual machine name.
      --waittime=300: Time in milliseconds to wait between port knocking retries during 'start'
error in run: config error: pflag: help requested

brb@NCI-01825357 /c/Program files/Boot2Docker for Windows

The big picture


                           start.sh                      docker run -it ubuntu bash
Git Bash Git Bash         ---------->  boot2docker-vm       ------------->   ubuntu
                                   docker@boot2docker:
   <-------               <----------                       <------------- 
   boot2docker down           exit                                 exit
   (shutdown boot2docker) (boot2docker-vm is still on)
    |
    |
    |  boot2docker up (start boot2docker)
    |
    |  boot2docker ssh (log into docker acct)
    |
    v
   boot2docker-vm
   docker@boot2docker

Increase boot2docker vmdk space

https://docs.docker.com/articles/b2d_volume_resize/

Install utilities in Boot2docker VM

http://blog.tutum.co/2014/11/05/how-to-use-docker-on-windows/

For example, to install cifs-utils,

wget http://distro.ibiblio.org/tinycorelinux/5.x/x86/tcz/cifs-utils.tcz
tce-load -i cifs-utils.tcz

WSL2

Mac

  • https://docs.docker.com/desktop/mac/
  • Alternatives to Docker Desktop for Mac? Rancher is recommended. 2022-06-08
  • Vagrant method. If you have Mac, you don't have to use boot2docker (iso & its management tool). You can use other Linux which comes with docker pre-installed. See this post.
  • To avoid the message Error: `brew cask` is no longer a `brew` command. Use `brew <command> --cask` instead, use
    brew install --cask docker
    

Raspberry Pi

ARM architeture from hub.docker.com

curl -sSL https://get.docker.com | sh
  • UDOO Quad running Armbian 20.04
    • The instruction on official Docker website does not work
    • The curl command method above does not work
    • sudo apt-get install -y docker.io works (docker -v shows it is 19.03.8). After that, run sudo usermod -aG docker $USER and log out/in.
  • See Odroid magazine 2015 January and 2015 February. Note that the current versions of Docker and Docker Hub are not aware of the architecture for which the image has been built. All standard images are intended for the x86 architecture, and the autobuild feature offered by the Docker registry is only available for x86.
  • NVIDIA Jetson Nano Developer Kit - Introduction, Redis running inside Docker container on NVIDIA Jetson Nano
sudo apt install curl
curl -sSL https://get.docker.com/ | sh

docker-compose

Some examples*

Not I use the arm64 image on my Pi3b+.

Images from https://www.linuxserver.io/. Some indices include number of pulls and stars.

List of tz database time zones

Portainer. The port number is 9000. Note the stack will be deployed using the equivalent of docker-compose. Only Compose file format version 2 is supported at the moment.

Samba. Tested on iOS, Ubuntu & Windows 10.

mkdir -p /mnt/usb/share/{data,backups}
mkdir /mnt/usb/share/data/{alice,bob,documents}
touch /mnt/usb/share/backups/backupsfile
touch /mnt/usb/share/data/bob/bobfile
touch /mnt/usb/share/data/documents/documentfile

docker run -d -p 445:445 \
  -v /mnt/usb/share/data:/share/data \
  -v /mnt/usb/share/backups:/share/backups \
  --name rpi-samba trnape/rpi-samba \
  -u "alice:abc123" \
  -u "bob:secret" \
  -u "guest:guest" \
  -s "Backup directory:/share/backups:rw:alice,bob" \
  -s "Bob (private):/share/data/bob:rw:bob" \
  -s "Documents (readonly):/share/data/documents:ro:guest,alice,bob" 

On Windows, 1) right click on 'This PC' and choose 'Add a network location'. 2) type \\192.168.1.249\ and the dropdown list will populate all available folders. 3) choose the one (e.g. Bob) and then enter the credential. Done. On Ubuntu, just type smb://192.168.1.249/. It will then populate the available folders.

Nginx

mkdir -p /mnt/usb/docker-nginx/html
echo "hello world" >> /mnt/usb/docker-nginx/html/index.html
nano /mnt/usb/docker-nginx/html/sharefile
docker run --name rpi-nginx -p 8086:80 \
  --restart always \
  -v /mnt/usb/docker-nginx/html:/usr/share/nginx/html \
  -d nginx:stable-alpine

# Or a stack file
version: '2'
services:
    nginx:
        container_name: rpi-nginx
        ports:
            - '8086:80'
        restart: always
        volumes:
            - '/mnt/usb/docker-nginx/html:/usr/share/nginx/html'
        image: nginx:stable-alpine

Note consider to use a samba share folder (see above) as a nginx document root.

cp /mnt/usb/docker-nginx/html/* /mnt/usb/share/data/bob/
rm -rf /mnt/usb/docker-nginx/html
ln -s /mnt/usb/share/data/bob/ /mnt/usb/docker-nginx/html

Rpi-monitor. I need to change /dev/vcsm to /dev/vcsm-cma. But the temperature part is not working. I am using 64-bit Raspberry Pi OS and it does not show attached USB disks. The port number is 8888.

code-server

---
version: "2.1"
services:
  code-server:
    image: ghcr.io/linuxserver/code-server
    container_name: code-server
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
      - PASSWORD=password #optional
      - SUDO_PASSWORD=password #optional
    volumes:
      - /mnt/usb/code-server:/config
    ports:
      - 8443:8443
    restart: unless-stopped

mstream Music streaming. Works great.

emby does not work on arm64. It works on x86 though. Even I copy a mp4 file to movies directory the movie does not show up:(

version: '2.1'
services:
    embyserver:
        container_name: emby
        network_mode: bridge
        restart: always
        environment:
            - VERSION=latest
            - UID=1000
            - GID=1000
            - TZ=America/Denver
        volumes:
            - /media/crucial/emby/config:/config
            - /media/crucial/emby/tv:/mnt/tv
            - /media/crucial/emby/movies:/mnt/movies
        ports:
            - 8096:8096            
        image: 'emby/embyserver:latest'

jellyfin Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. How to Install Jellyfin on Docker with Portainer

plex We can access the plex server via http://IP:32400/web. Note that in the first server setup, we need to add Library' by choosing the new library name (eg Other Videos) shown on plex & the data source (eg /data) so our own media can be found. After we added new media files we can rescan by clicking the vertical 3 dots icon and selecting scan library files. Pi3b+ is still a little weak since I can see all threads are busy when I played a mp4 file.

mkdir -p /mnt/usb/plex/{config,data}
cp FILENAme.mp4 /mnt/usb/plex/data
docker run \
  -d \
  --name plex \
  --net host \
  -p 32400:32400 \
  --restart always \
  --volume /mnt/usb/plex/config:/config \
  --volume /mnt/usb/plex/data:/data \
  greensheep/plex-server-docker-rpi:latest

WARNING: The requested image's platform (linux/arm) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

Nextcloud.

sudo mkdir -p /srv/dev-disk-by-label-Files/Databases/NextCloud
sudo mkdir -p /srv/dev-disk-by-label-Files/Config/Nextcloud

After that, copy and paste the stack into portainer. Wait for a few minutes on RPi3. The port number is 8080. Now we can create the admin username/password such as nextcloud/nextcloud. Click the little triangle next to "Storage and Database". Change to MySQL. In the next part we enter nextcloud/nextcloud/nextcloud/db (note the "db" replaces localhost b/c we use "db" as the service name). Again, wait for a few minutes.

Heimdall (Dashboard for web apps). I keep the PUID (1000) and PGID (1000). The instruction says it is from the admin user account but I don't find admin account? Change the volume to /srv/dev-disk-by-label-Files/Config/Heimdall (use sudo mkdir to create the directory on terminal). Change the port to 83 & remove port 443. Define the endpoint from Portainer -> Endpoints -> local -> Public IP as raspberrypi.local (depending on your hostname). We need to wait a little bit. Now go to the container and find heimdall and click the port in order to open the website correctly (instead 0.0.0.0). I can add apps like nextcloud, portainer, pi-hole, other servers, etc. The Application Type entry has a good list of popular apps and it will pre-populate the button icon and the background color for our app.

taisun The default port is 3000

yacht. The default login is [email protected] and pass. The name shown on portainer is pedantic_hermann

docker volume create yacht
docker run -d -p 8001:8000 -v /var/run/docker.sock:/var/run/docker.sock -v yacht:/config selfhostedpro/yacht

CloudFlare DDNS - Update CloudFlare with Your Dynamic IP Address

WatchTower. It has some bugs; for example, Error response from daemon: client version 1.25 is too old

bitwardenrs. Use the terminal to create a volume first. The port number is 8100. This is straightforward.

Duplicati for backup.

photoshow. It works. It has a slideshow button. PhotoShow only displays videos in WebM.

R. r-base provide arm64 image but not not 32-bit arm architecture.

# 64-bit OS
docker pull r-base
docker run -it --rm r-base   # enter R directly

rocker/rstudio DOES NOT work on arm64 even I can pull. WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

I build a 32-bit armv7 image for r-base v4.0.2. This image works on either 32-bit or 64-bit arm OS (tested on 32-/64-bit Raspberry Pi and other 32-bit SBC devices).

docker pull arraytools/r402armv7
docker run -it --rm arraytools/r402armv7 R
docker pull r-base
# Using default tag: latest
# latest: Pulling from library/r-base
# no matching manifest for linux/arm/v7 in the manifest list entries

How and Why to Use A Remote Docker Host

Backup

Usage

Basics, docs, cheatsheet, introduction

Note that we need sudo is needed unless it is on a Mac OS.

If docker cannot find an image, it will try to pull it from its repository.

$ sudo docker run -it ubuntu /bin/bash
Unable to find image 'ubuntu' locally
Pulling repository ubuntu
04c5d3b7b065: Download complete 
511136ea3c5a: Download complete 
c7b7c6419568: Download complete 
70c8faa62a44: Download complete 
d735006ad9c1: Download complete 
root@ec83b3ac878d:/# 
purpose command
run a container docker container run -d -p 80:80 httpd
list running cotainer docker container ls
view logs of Docker container docker container logs cranky_cori
identify Docker container process? docker container top cranky_cori
stop Docker container? docker container stop cranky_cori
list stopped or not running Docker containers docker container ls -a
start Docker container docker container start c46f2e9e4690
remove Docker container docker container rm cranky_cori
list Docker images docker images
remove Docker image docker rmi iman/touch

Restart docker daemon

When I try the Chap5 > Continuous integration (Jenkins) of the Docker Book, I found I cannot stop/kill the container. See others' report here. The solution is to restart the docker daemon.

sudo service docker start

After that, I can stop and rm the container.

sudo docker stop jenkins
sudo docker rm jenkins
sudo docker ps -a

images vs containers

$ sudo docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
iman                           latest              6e0f5644b2fd        About a minute ago   460.4 MB
iman/touch                     latest              77b9ac5951c2        4 minutes ago        460.4 MB
<none>                         <none>              aaa75e64ddf0        5 weeks ago          188.3 MB
ouruser/sinatra                v2                  ea8c9f407a8d        5 weeks ago          447 MB
ubuntu                         14.04               ed5a78b7b42b        5 weeks ago          188.3 MB
ubuntu                         latest              ed5a78b7b42b        5 weeks ago          188.3 MB
eddelbuettel/docker-ubuntu-r   add-r-devel-san     3c19d078c5d9        3 months ago         460.4 MB
hello-world                    latest              ef872312fe1b        4 months ago         910 B
training/sinatra               latest              f0f4ab557f95        8 months ago         447 MB

$ sudo docker ps -a
CONTAINER ID IMAGE                                          COMMAND              CREATED        STATUS                   PORTS NAMES
8fbdbcdb5126 iman/touch:latest                              "/bin/bash"          2 minutes ago  Exited (0) 2 minutes ago       thirsty_engelbart   
dc9e82f2c00a eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          9 minutes ago  Exited (0) 3 minutes ago       kickass_bardeen     
532a90f36aa8 eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          18 hours ago   Exited (0) 18 hours ago        happy_lalande       
7634024ee0bf eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          18 hours ago   Exited (0) 18 hours ago        insane_mclean       
14034a9720cb eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          18 hours ago   Exited (0) 18 hours ago        naughty_lumiere     
ca90954628db eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          19 hours ago   Exited (130) 18 hours ago      sick_hawking        
8bbdcb7c339f eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          19 hours ago   Exited (0) 19 hours ago        modest_davinci      
e8e24f80f0dd aaa75e64ddf0                                   "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago       berserk_hodgkin     
d41959e0eb55 aaa75e64ddf0                                   "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago       jovial_curie        
b408c0e2805b aaa75e64ddf0                                   "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago       lonely_tesla        
72a551e4b492 ouruser/sinatra:v2                             "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago         jolly_meitner       
75fd6cc4658b training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago         evil_yalow          
cc8886f5a02e training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (130) 5 weeks ago       elegant_curie       
0585e4f5fecd eddelbuettel/docker-ubuntu-r:add-r-devel-san   "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago         elated_euclid       
brb@brbweb4:~/Downloads$ 

When we want to delete a container, we use the container's CONTAINER ID or NAME (last column output from docker ps -a). But when we want to delete an image, we use the image's REPOSITORY or IMAGE ID (2nd column output from docker images)

$ sudo docker rm thirsty_engelbart  # iman/touch
$ sudo docker rm dc9e82f2c00a       # eddelbuettel/docker-ubuntu-r:add-r-devel-san
$ sudo docker ps -a   # check to see the container is gone now

$ sudo docker rmi 6e0f5644b2fd
$ sudo docker rmi iman/touch
$ sudo docker images  # check to see the images are gone now

Command line interface, CLI

https://docs.docker.com/engine/reference/commandline/cli/ Docker command line

$ docker

Usage:	docker COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/home/brb/.docker")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/home/brb/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/home/brb/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/home/brb/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  config      Manage Docker configs
  container   Manage containers
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.

Version, system information

Docker version

$ docker version
Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a
 Built:             Tue Aug 21 17:24:51 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a
  Built:            Tue Aug 21 17:23:15 2018
  OS/Arch:          linux/amd64
  Experimental:     false

System information.

  • what mode the Docker engine is operating in (swarm mode or not)
  • what storage drive is used for the union filesystem
  • what version of the Linux kernel we have on our host
  • et al
$ docker system info
Containers: 2
 Running: 0
 Paused: 0
 Stopped: 2
Images: 10
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
 apparmor
 seccomp
  Profile: default
Kernel Version: 4.15.0-33-generic
Operating System: Ubuntu 18.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.674GiB
Name: t420s
ID: VLWB:6BN3:U7KB:L4T4:GQIB:54F3:YZKJ:PAIR:HEUM:UQIC:XLZU:3IFJ
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

WARNING: No swap limit support

List resource consumption

$ docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              10                  2                   2.58GB              1.519GB (58%)
Containers          2                   0                   304B                304B (100%)
Local Volumes       2                   0                   314.7MB             314.7MB (100%)
Build Cache         0                   0                   0B                  0B

$ docker system df -v  # more detailed information
# We can use the information to clean up our system

A brief intro to docker virtualization

docker search --help
docker search redis
docker search -s 100 redis
docker pull --help
docker pull ubuntu # download all versions of ubuntu
docker images    # available local container images
docker pull centos:latest
docker run --help
cat /etc/issue   # look at the current distr name before running docker
docker run -it centos:latest /bin/bash
                 # create a container & execute as a sudo

cat /etc/redhat-release
yum
cd /home
touch temp.txt
ls
exit

docker ps   # current running processes
docker ps -a # show all processes including closed
docker restart c85850ed0e13
docker ps   # container c85850ed0e13 is running
docker attach c85850ed0e13 # log into the system

ls /home
exit

docker ps -a
docker rm c85850ed0e13 # delete the container

Note: Following the discussion, using attach can only launch one instance of shell. If we use exec, we can launch multiple instances.

sudo docker exec -i -t c85850ed0e13 bash #by ID
or
$ sudo docker exec -i -t loving_heisenberg bash #by Name

Rootless mode

  • Run the Docker daemon as a non-root user (Rootless mode)
    • The data dir is set to ~/.local/share/docker by default. The data dir should not be on NFS.
  • Setup on Ubuntu 22.04
    curl -fsSL https://get.docker.com | bash
    sudo apt install -y uidmap
    dockerd-rootless-setuptool.sh install
    nano ~/.bashrc
    
    source ~/.bashrc
    
    systemctl --user start docker
    systemctl --user enable docker
    sudo loginctl enable-linger $(whoami)
    
    docker run hello-world
    docker run --rm -ti r-base:4.4.1
  • Unfortunately, Rocker/rstudio does not work. I am not able to log in using username/password. It keeps saying incorrect username/password.
  • Limitations:
    • Performance Overhead
      • OverlayFS Limitations: Rootless Docker uses fuse-overlayfs instead of OverlayFS by default, which can be slower.
      • Resource Limits: The performance might be slightly lower compared to running Docker with root privileges due to additional user namespace operations.
    • Network Restrictions
      • Network Drivers: Only the bridge and host network drivers are supported. macvlan and overlay network drivers are not supported.
      • Port Binding: Binding to ports below 1024 is not allowed. Only non-privileged ports (1024 and above) can be used.
    • File System
      • Volume Permissions: Issues with file permissions can arise when mounting volumes from the host, as the files created by rootless Docker processes will be owned by the user running Docker, not root.
      • NFS and Other Filesystems: Certain filesystems like NFS might have compatibility issues with rootless Docker due to permission and ownership constraints.
    • Compatibility
      • Certain Features: Some Docker features might not be fully supported or behave differently. For example, checkpoint/restore and cgroup v1 are not supported.
      • Security Features: Some security features like AppArmor, SELinux, and seccomp might have limited functionality or require additional configuration.
    • Configuration Complexity
    • Troubleshooting
  • What's the difference between rootless Docker, running a container as a non-root user, and Podman?
  • Docker Running In Rootless Mode
  • Going rootless with Docker and Containers
  • How to Run Rootless Docker Containers
  • How To Migrate To Rootless Docker In Debian And Ubuntu Linux

docker pull

https://docs.docker.com/engine/reference/commandline/pull/

$ docker pull ubuntu:zesty
$ docker run -ti --rm ubuntu:zesty /bin/bash 
# lsb_release -a         
bash: lsb_release: command not found
# cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=17.04
DISTRIB_CODENAME=zesty
DISTRIB_DESCRIPTION="Ubuntu 17.04"
NAME="Ubuntu"
VERSION="17.04 (Zesty Zapus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 17.04"
VERSION_ID="17.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=zesty
UBUNTU_CODENAME=zesty

Update/upgrade images

docker compose pull && docker compose up -d
docker compose up --pull always -d

<none>:<none> images

Exit/detach from a container without stopping it

$ docker container run -it ubuntu:latest /bin/bash
# Ctrl+p, Ctrl+q to exit the container without terminating it
$ docker ps -a # showing the container 70c5aceb5512 is running in the background

# You can reattach your terminal to it with the "docker container exec" command
$ docker container exec -it 70c5aceb5512 bash

How to start a stopped Docker container with a different command

How to start a stopped Docker container with a different command?

Clean shutdown DOCKER containers before reboot

Dockerizing Applications/Detached mode

$ sudo docker run -d --name insane_babbage ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
$ sudo docker ps -l
$ sudo docker logs insane_babbage
$ sudo docker stop insane_babbage
$ sudo docker ps

The -d flag tells Docker to run the container and put it in the background, to daemonize it.

According to https://docs.docker.com/engine/reference/run/#detached-vs-foreground, containers started in detached mode exit when the root process used to run the container exits, unless you also specify the --rm option. If you use -d with --rm, the container is removed when it is stopped, exits or when the daemon exits, whichever happens first.

Automatically restart after reboot

https://stackoverflow.com/questions/18786054/how-to-auto-restart-a-docker-container-after-a-reboot-in-coreos

Add a --restart=always parameter. It will always restart a stopped container unless it has been explicitly stopped, such as via a "docker container stop" command. See the following

$ docker run -d --restart always myCustomeDocker

$ docker container run --name neverdie -it --restart always ubuntu /bin/bash
# exit
$ docker ps -a  # the container is still ther
$ docker stop neverdie
$ docker ps -a

Working with Containers

$ sudo docker run -i -t ubuntu /bin/bash
$ sudo docker version
$ sudo docker
$ sudo docker attach --help

Environment variables

Select columns from "docker ps" output

Below will output (and reorder) the NAME, CONTAINER ID, IMAGE and Ports columns only from regular "docker ps" output. The COMMAND, CREATED, and STATUS columns will be skipped.

alias dockerps='docker ps --format "{{printf \"%-12s\" .Names}}{{printf \"%-15s\" .ID}}{{printf \"%-30s\" .Image}}{{printf \"%-25s\" .Ports}}"'

Docker container ID

  • The full container ID is a hexadecimal string of 64 characters.
  • The minimum number of characters required for a Docker ID is 4.
  • We can use a shorter ID in docker command if that ID uniquely determined the container. For example, docker exec -it 9608 bash or even docker exec -it 9 bash works.

Alpine image

apk add htop

Running a Web Application

$ sudo docker run -d -P training/webapp python app.py

Alpine linux is 6MB. It is a good OS to run a web application. See the demo here.

Viewing our Web Application Container

$ sudo docker ps -l
$ sudo docker run -d -p 5000:5000 training/webapp python app.py

Monitor, Check container status (docker status) - CPU, Memory usage

Container networking

Host network

  • If you use the host network driver for a container, that container’s network stack is not isolated from the Docker host. For instance, if you run a container which binds to port 80 and you use host networking, the container’s application will be available on port 80 on the host’s IP address.
  • One good example is if I want to use tailscale network from my host in Uptime Kuma container. See HERE.
  • Considerations. While host networking can be powerful, it's important to consider:
    • Security implications: Host networking reduces network isolation, potentially increasing security risks.
    • Port conflicts: Services using host networking may conflict with other applications running on the host machine.
    • Platform limitations: Host network mode only works on Linux hosts, not on Docker Desktop for Mac or Windows.

ping, ifconfig and ip commands not found in Ubuntu container

apt update
apt install iputils-ping  # ping 
apt install net-tools     # ifconfig
apt install iproute2      # ip

Network Port Shortcut

$ sudo docker port nostalgic_morse 5000

Access Ports on the Host from a Docker Container

How to Access Ports on the Host from a Docker Container

Multiple NICs

containers in docker to use public ip addresses directly

Viewing the Web Application's Logs

Clear Logs of Running Docker Containers

Looking at our Web Application Container's processes

$ sudo docker top nostalgic_morse

Inspect the linux distribution of the base image

$ docker inspect rocker/shiny:4.4.0

In the Labels section of the output, we see the following line:

"org.opencontainers.image.base.name": "docker.io/library/ubuntu:jammy"

This indicates that the base image for rocker/shiny:4.4.0 is bsaed on Ubuntu Jammy.

Inspecting our Web Application Container

$ docker inspect nostalgic_morse

Obtain the container's IP address, log into a running server

PS. Portainer web interface can show the IP addresses.

$ docker inspect <container id> | grep "IPAddress"

We don't need the IP address if we just want to log into a running server,

$ docker exec -it <contianer id> bash

How to Secure Docker’s TCP Socket

How to Secure Docker’s TCP Socket with TLS

docker attach

Suppose I run docker run -it --user rstudio bioconductor/bioconductor_docker:devel R and I use q() to quit the container. The container is still there. To re-enter the R in the container, I use

docker start XXXXXXXX    # restart it in the background
docker attach XXXXXXXX   # reattach the terminal to a running container

If we want the latest created container, then we use

docker start `docker ps -q -l` && docker attach `docker ps -q -l`

docker exec: SSH into a running container

Run a command in a running container

  • Usage:
    docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
  • Examples:
    $ docker exec -d ubuntu_bash touch /tmp/execWorks # do st in the background
    
    $ docker exec -it ubuntu_bash bash
    
    $ docker exec -it -e VAR=1 ubuntu_bash bash # set an environment variable
    
    $ docker exec -it ubuntu_bash pwd
    $ docker exec -it -w /root ubuntu_bash pwd # change the working directory
  • How to Run a Command on a Running Docker Container
  • How to Use the Docker exec Command. nginx container is used as an example.
    docker run --name docker-nginx -p 8080:80 -d nginx
    
    # method 1. Access the Running Container’s Shell
    docker exec -it ID /bin/bash
      apt-get update
      apt-get upgrade -y
      exit
    
    # method 2. Run a Command from Outside the Container
    docker exec ID apt-get update && apt-get upgrade
    
    docker exec ID cat /usr/share/nginx/html/index.html
    docker cp index.html ID:/usr/share/nginx/html/
    docker exec ID cat /usr/share/nginx/html/index.html
    

docker cp

Copy files/folders between a container and the local filesystem.

Restart an exited Container

$ docker start nostalgic_morse
OR
$ docker restart nostalgic_morse

For an interactive container, use docker start -ai CONTAINER which is equal to run "docker start CONTAINER" and "docker attach CONTAINER".

Rename a container

docker container rename

docker container rename CONTAINER NEW_NAME

Inspect container images and their metadata

Know the container size

docker ps -s

Meaning of two sizes

  • The "size" information shows the amount of data (on disk) that is used for the writable layer of each container
  • The "virtual size" is the amount of disk-space used for the read-only image data used by the container.

Removing our Web Application Container

$ sudo docker stop nostalgic_morse
$ sudo docker rm nostalgic_morse

Note: Always remember that deleting a container is final!

Dockerize an SSH service

https://docs.docker.com/engine/examples/running_ssh_service/#environment-variables

Remove old docker containers

This post on stackoverflow.com.

$ sudo docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs --no-run-if-empty sudo docker rm

Similarly to remove all exited containers

$ sudo docker ps -a | grep Exit | awk '{print $1}' | xargs sudo docker rm

To kill/stop (not delete) all running containers

$ sudo docker kill $(sudo docker ps -q)

To delete all stopped containers

$ sudo docker rm $(sudo docker ps -a -q)
OR
$ sudo docker rm `sudo docker ps -a -q`

It is also helpful to create bash aliases for these commands by editing ~/.bash_aliases file.

docker create vs docker run

https://stackoverflow.com/questions/37744961/docker-run-vs-create

docker create is similar to docker run -d except the container is never started.

Retrieve docker run command

https://stackoverflow.com/a/32774347. See the github page of runlike. So it is better to put the docker run in a stack. Then for example the Portainer has an Editor tab to show the compose file.

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    assaflavie/runlike -p CONTAINER_NAME

The -p option splits the output into pretty lines.

docker run -it and -d together

How to Modify the Configuration of Running Docker Containers

How to Modify the Configuration of Running Docker Containers

Volume

Examples of host's volume locations

/home/$USER/docker/$PROJECT/$SUB-DIRECTORY

PUID, PGID, share volume permission/owner

  • Understanding PUID and PGID (or the source)
  • How to Create Users in Linux (for testing the case the user id is not 1000)
    sudo adduser jane # create /home/jane 
    sudo id jane      # it should not be 1000
                      # so we can do some testing
    sudo nano /etc/sudoers # add jane
    su - jane    # switch to /home/jane
    # Add a user to the docker group and immediately apply the changes without requiring the user to log out and back in
    sudo usermod -aG docker $USER; newgrp docker
    
    # Test some examples
    docker run --rm -ti --user docker -v "$(pwd)":/workspace r-base 
    > setwd("/workspace")
    Error in setwd("/workspace") : cannot change working directory
    
    docker run --rm -ti --user $(id -u):$(id -g) -v "$(pwd)":/workspace r-base
    # telling Docker to run the container as your current host user.
    > setwd("/workspace")
    # Writing works. But the file owner is an id, not my user name
  • You should use the -e PUID and -e PGID options when creating a container from a Docker image to map the container’s internal user to a user on the host machine. This is useful because Docker runs all of its containers under the root user domain, which means that processes running inside your containers also run as root. This kind of elevated access is not ideal for day-to-day use and can potentially give applications access to things they shouldn’t. By using PUID and PGID, you can ensure that files and directories created during the container’s lifespan are owned by a user on the host machine instead of root.
  • Please note that not all Docker images support the PUID and PGID environment variables. The Docker image must be designed to use these variables. If you’re using an image that doesn’t support these variables, you may need to create a Dockerfile to build a new image that does.
  • The following works. The --user option is a built-in Docker feature that sets the user (and optionally the group) that is used to run the container. This option works regardless of whether the Docker image uses any specific environment variables. PS. "docker" user has been defined in the r-base's Dockerfile.
    docker run --rm -ti --user docker \
      -v "$(pwd)":/workspace r-base 
    > setwd("/workspace")
    > save(iris, file="iris.rda")
    > system("ls -lt") # docker docker instead of $USER $USER
    > unlink("iris.rda")
  • Similarly, the --user option works with rocker/rstudio image and ubuntu.
    docker run --rm -ti --user rstudio \
      -v "$(pwd)":/workspace rocker/rstudio R
    > setwd("/workspace")
    > save(iris, file="iris.rda")
    > system("ls -lt")
    > unlink("iris.rda")

    Note that the prompt is $ rather than #.

    docker run --rm -it -v $(pwd):/home --user ubuntu \
       ubuntu bash
    $ id
    uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev)
    $ cd /home
    $ echo "newfile" > newfile
    
    docker run --rm -it -v $(pwd):/home --user "$(id -u):$(id -g)" \
       ubuntu bash
    $ cd /home
    $ echo "newfile" > newfile
  • In the article Sharing files with host machine from the Rocker's project, users are instructed to use -e USERID variable if the host machine user has a UID other than 1000. But the generated file 'iris.rda' from the following example is still owned by root:(
    docker run --rm -ti -v "$(pwd)":/workspace -e USERID=$UID rocker/rstudio R
  • (Cont.) however, if we run the above command as a daemon and log in using the user "rstudio" , it works even we don't specify the "-e USERID" option. The lesson is we should use the user defined in the docker image.
    docker run --rm -v "$(pwd)":/workspace -p PASSWORD=123 rocker/rstudio
    

    Notice the prompt is # rather than $ and the user id is 0.

    docker run --rm -it -v $(pwd):/home -e PUID=1000 -e PGID=1000 \
      ubuntu bash
    # id
    uid=0(root) gid=0(root) groups=0(root)
    
  • In this video How to Install Calibre on OMV and Docker, it uses the command id admin where "admin" is the portainer user to get PUID (of "admin") and PGID (of "users") to find out the two ids.
  • Shiny application with output files, github.

Back Up Your Docker Volumes

How to Back Up Your Docker Volumes

Two ways to achieve persistent data

Inspect the 'Mountpoint' of a volume

$ docker volume create crv
$ docker volume ls

$ docker run -d \
     --name mycloud \
     -p 81:80 \
     -v apps:/var/www/html/custom_apps \
     nextcloud

# docker inspect is not quite useful. It does not show how the volume was created
# But we can examine (ls, du, ...) the directory contents
$ docker inspect apps   
[
    {
        "CreatedAt": "2018-10-23T09:41:52-04:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/apps/_data",
        "Name": "apps",
        "Options": null,
        "Scope": "local"
    }
]

Remove an an unnamed volume

I you want to automatically removes volumes when a container is removed, you can use the --rm flag when starting the container with the "docker run" command. This flag tells Docker to automatically remove the container and any anonymous volumes associated with it when the container exits. However, this flag does not affect named volumes.

If you created an unnamed volume, it can be deleted at the same time as the container with the -v flag. Note that this only works with unnamed volumes.

docker rm -v container_name

If the volume is named, it stays present. To remove a named volume, use docker volume rm volume_name .

Volumes created in docker-compose

When you use docker-compose to create and manage containers, volumes are handled slightly differently than when using the docker run command.

In a "docker-compose.yml" file, you can specify named volumes using the volumes key at the top level of the file. These volumes are created when you run docker-compose up and are not automatically removed when you stop or remove the containers using docker-compose down.

If you want to remove named volumes created by docker-compose, you can use the -v flag with the docker-compose down command. Here’s an example command that stops and removes all containers defined in a docker-compose.yml file and also removes any named volumes:

docker-compose down -v

This command stops and removes all containers defined in the docker-compose.yml file and also removes any named volumes specified in the file. All data stored in the volumes will be permanently deleted.

Anonymous volumes created by docker-compose are automatically removed when you stop and remove the containers using docker-compose down, even if you don’t use the -v flag.

Start a container with a volume

--mount -v
docker run -d \

--name devtest \
--mount source=myvol2,target=/app \
nginx:latest

docker run -d \

--name devtest \
-v myvol2:/app \
nginx:latext

Note

  • target in "--mount" can be replaced by destination or dst.
  • To use a read-only volume, add the ,readonly option in "--mount" or the :ro option in "-v".
  • We cannot use "~/" to represent a local directory under HOME. We have to specify a full path in docker run.

A simple example

From the book "Learn Docerk -Fundamentals of Docker 18.x". Chap 5. Data Volumes and System Management > Creating and mounting data volumes.

# Create a volume
docker volume create my-data
docker volume inspect my-data
# The host folder can be found in the output under 'Mountpoint'
# In my case,
#        "Mountpoint": "/var/lib/docker/volumes/my-data/_data",

# Mount a volume into a container
docker run --name test -it -v my-data:/data alpine /bin/sh
# cd /data
# echo 'some data' > data.txt
# echo 'more data' > data2.txt
# exit
docker inspect my-data
sudo ls /var/lib/docker/volumes/my-data/_data
# We can even try to output the content of say, the second file:
sudo cat /var/lib/docker/volumes/my-data/_data/data2.txt
# We can create a new file in this folder from the host and then use the volume with another container
echo "the file is created on host" > sudo tee /var/lib/docker/volumes/my-data/_data/host-data
# Let's delete the test container and run another one
docker rm test

# This time we are mounting our volume to a different container folder
docker run --name test2 -it -v my-data:/app/data centos:7 /bin/bash
# We are able to see three files:
# ls /app/data

# Remove volumes
docker volume rm my-data # Or 
docker volume rm $(docker volume ls -q)

# Remove all running containers to clean up the system,
docker rm -f $(docker ls -aq)

Sharing data between containers

How to Share Data Between Docker Containers

docker run -it --name writer -v shared-data:/data alpine /bin/sh
# create a file inside it
# echo 'my sample file' > /data/sample.txt
# exit
docker run -it --name reader -v shared-data:/app/data:ro ubuntu:17.04 /bin/bash
# ls -l /app/data

Using host volumes

Use volumes that mount a specific host folder

  • It may be possible for the "docker volume" command to mount a local directory to a volume. See examples in the "docker volume create" documentation.
  • Specifying a directory name instead of giving a volume name in the "docker run" 's -v option
  • Since we are specifying a directory name instead of letting docker to create a new volume, "docker volume ls" will not getting a new volume
docker run -it --name test -v $(pwd)/src:/app/src alpine /bin/sh

# Make a sample to demonstrate how that works
mkdir ~/my-web; cd ~/my-web
echo "<h1>My website</h1>" > index.html

# Create 'Dockerfile'
echo -e 'FROM nginx:alpine
COPY . /usr/share/nginx/html' > Dockerfile

docker image build -t my-website:1.0 .
docker run -d -p 8080:80 --name my-site my-website:1.0

# Open http://localhost:8080. It looks good
# Now modify index.html and refresh the website. It does not refresh
# Let's stop and rm the container and rebuild using a volume
docker rm -f my-site
docker run -d -v $(pwd):/usr/share/nginx/html \
   -p 8080:80 --name my-site my-website:1.0
# Now any changes on index.html will refresh on the website

Define volumes in images

A few samples of volume definition

VOLUME /app/data
VOLUME /app/data, /app/profiles, /app/config
VOLUME {"/app/data", "/app/profiles", "/app/config"]

The first line defines a single volume to be mounted at /app/data.

We can use the docker image inspect command to get information about the volumes defined in the Dockerfile.

docker image pull mongo:3.7
docker image inspect --format='{{json .ContainerConfig.Volumes}}' \
       mongo:3.7 | jq
# {
#   "/data/configdb": {},
#   "/data/db": {}
# }

# now run an instance of MongoDB and inspect the volume information
docker run --name my-mongo -d mongo:3.7
docker inspect --format '{{json .Mounts}}' my-mongo | jq
# [
#  {
#    "Type": "volume",
#    "Name": "535e0138b9a32e89f71380e9e73bb0de64ce0d1cad78fcda0ec1d49e11d76d7a",
#    "Source": "/var/lib/docker/volumes/535e0138b9a32e89f71380e9e73bb0de64ce0d1.../_data",
#    "Destination": "/data/configdb",
#    "Driver": "local",
#    "Mode": "",
#    "RW": true,
#    "Propagation": ""
#  },
#  {
#    "Type": "volume",
# SKIP

Differences between VOLUME and '-v|--volume'

https://stackoverflow.com/a/25312719

Container Memory Limits, Setting Available CPUs, Allocating memory and CPU

docker run \
    -rm \ ## Automatically remove the container when it exits
    --memory=6g \ ## memory limit
    --cpus=1.5 \ ## number of CPUs
    -v /shared/data-store:/home/rstudio/data \
    -v /shared/library-store:/usr/local/lib/R/host-site-library \
    -e PASSWORD=bioc \
    -p 8787:8787 \
         bioconductor/bioconductor_full:devel

Work with container images

List images by size or name

# by size
docker images --format "{{.ID}}\t{{.Size}}\t{{.Repository}}" | sort -k 2 -h

# by name
docker images --format "{{.ID}}\t{{.Size}}\t{{.Repository}}" | sort -k 3 

List specific columns

docker images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}'

Create an image interactively using commit - Example 1

The example is from the book 'Learn Docker - Fundamentals of Docker 18.x'.

docker container run -it --name sample alpine /bin/sh
# apk update && apk add iputils
# ping 127.0.0.1
# exit
docker container ls -a | grep sample
docker container diff sample

We can now use the docker container commit command to persist our modifications and create a new image from them

docker container commit sample my-alpine
docker images ls

If we want to see how our custom image has been built, we can use the history command as follows:

docker image history my-alpine
# IMAGE               CREATED              CREATED BY                                      SIZE    COMMENT
# 0f105057899b        About a minute ago   /bin/sh                                         1.55MB              
# 196d12cf6ab1        4 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B                  
# <missing>           4 weeks ago          /bin/sh -c #(nop) ADD file:25c10b1d1b41d46a1…   4.41MB

The first layer in the preceding list is the one we just created by adding the iputils package.

Create an image interactively using commit - Example 2

Note that it is better/necessary to put the Dockerfile in an empty directory to avoid the problem of taking a long time to build the image (sending build context to Docker daemon ...GB ) since it will grab files from the current directory.

sudo docker search sinatra
sudo docker pull training/sinatra
sudo docker run -t -i training/sinatra /bin/bash
sudo docker commit -m="Added json gem" -a="Kate Smith" 0b2616b0e5a8 ouruser/sinatra:v2
sudo docker images

mkdir sinatra
cd sinatra
touch Dockerfile
sudo docker build -t="ouruser/sinatra:v2" .
sudo docker push ouruser/sinatra
sudo docker rmi training/sinatra
  • I get an error when I try to launch sinatra on my 32-bit ubuntu (Docker can only be installed through apt-get on 32-bit)
$ sudo docker run -t -i training/sinatra /bin/bash
2014/12/31 02:43:26 exec format error

How to copy Docker images from one host to another without using a repository

https://stackoverflow.com/questions/23935141/how-to-copy-docker-images-from-one-host-to-another-without-using-a-repository

docker save -o out.tar <image name>
# Or better to compress the file
docker save <docker image name> | gzip > out.tar.gz

And restore

docker load -i out.tar
# Or decompress the file
docker load < out.tar.gz

Docker Image Manifest

What Is a Docker Image Manifest?

Resources allocated to a container using docker?

https://stackoverflow.com/questions/16084741/how-do-i-set-resources-allocated-to-a-container-using-docker

hub.docker.com

docker tag local-image:tagname new-repo:tagname
docker login
docker push new-repo:tagname
docker pull phusion/baseimage
docker run -ti phusion/baseimage /bin/bash
  • https://dockerfile.github.io/ which includes dockerfiles for different purposes. The ubuntu-desktop one also works well (client needs a vnc viewer in order to see the desktop).

Set up a private Docker registry

$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:5000/v2/_catalog
$ OR
$ curl -H "Accept: application/xml" -H "Content-Type: application/json" -X GET http://localhost:5000/v2/_catalog

Github registry

docker pull ghcr.io/OWNER/IMAGE_NAME:TAG

# docker pull registry-url/image-name:tag

Google Container Registry

  • Authenticate with Google Cloud: ensure you have the Google Cloud SDK installed
    gcloud auth login
    gcloud auth configure-docker
    
  • Pull the image
    docker pull gcr.io/PROJECT_ID/IMAGE_NAME:TAG
    

Google Artifact Registry

https://cloud.google.com/artifact-registry/

  • Authenticate with Google Cloud: ensure you have the Google Cloud SDK installed
    gcloud auth login
    gcloud auth configure-docker us-central1-docker.pkg.dev
    
  • Pull the image
    docker pull us-central1-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME:TAG
    

Dockerfile

  • A Dockerfile does not follow the YAML syntax or the shell syntax. It is a plain text file that contains instructions for building a Docker image, using its own specific syntax and keywords.
  • Dockerfile Reference
  • Using Dockerfiles to Automate Building of Images from digitalocean.com.
  • Remember to put the Dockerfile in an empty directory.
  • What goes into a Dockerfile
  • Keywords
    • FROM. If we want to start from scratch, we can use FROM scratch.
    • RUN. The argument for RUN is any valid Linux command.
    • USER. This is useful if we want to create new files with a non-root owner privilege. For example, new files created under a binding directory with a non-root user ownership will belong to the current user in the host system. Here is an example where we use Rmarkdown to create pdf output. The generated pdf file should not be own by root. How to add users to Docker container? Switch users.
    • COPY & ADD.
      • "COPY . /app" will copy all files and folders from the current directory recursively to the /app folder. We can use "ADD" too but "ADD" will automatically unpack tarballs. See What is the difference between the `COPY` and `ADD` commands in a Dockerfile?
      • "ADD sample.tar /app/bin" will unpack the sample.tar' file into the target folder
      • "ADD http://example.com/sample.txt /data/" will copy the remote file sample.txt into the target file
    • WORKDIR. Define the working directory or context that is used when a container is run from the image.
    • CMD & ENTRYPOINT. These two are actually definitions of what will happen when a container is started from the image.
      • Use CMD without ENTRYPOINT: "CMD command param1 param2". This form is called the shell form.
      • If we use ENTRYPOINT + CMD, ENTRYPOINT defines the command and CMD defines parameters. The example above will run ping 8.8.8.8 -c 3. This form is called the exec form.
  • The Docker Book

Examples of Dockerfile

FROM python:2.7
RUN mkdir -p /app
WORKDIR /app
COPY ./requirements.txt /app/
RUN pip install -r requirements.txt
CMD ["python", "main.py"]
  • Another example
FROM alpine:latest
ENTRYPOINT ["ping"]
CMD ["8.8.8.8", "-c", "3"]
FROM debian:testing
RUN useradd docker \
	&& mkdir /home/docker \
	&& chown docker:docker /home/docker \
	&& addgroup docker staff

We can test it by "docker build -t mydebian . " and "docker run --rm -it --user docker -v /tmp:/home/docker mydebian". We can create a new file under /home/docker and the file will be accessible and belongs to the current host user once we quit the container. This actually is a huge security issue.

The same technique does not work on alpine if I try to create a new file in the container.

FROM alpine:latest
# Create a group and user; not useful for creating files in host OS
RUN addgroup -S appgroup && adduser -S appuser -G appgroup \
           && chown appuser:appgroup /home/appuser

"docker build -t myalpine . " and "docker run --rm -it -v ~/Downloads/:/home/appuser:rw --user appuser myalpine". When I use the "id" command in the container, I see it returns 100 in alpine container and 1000 in debian container. The id returns 1000 on my host (Ubuntu/Pop_OS). So the solution is docker run --rm -it -v ~/Downloads/:/home/appuser --user 1000:1000 myalpine. So the local user and the created user home directory in the container are not needed. See

Rocker

FROM r-base:latest
COPY check.R .
CMD [ "Rscript", "check.R", "/unsafe.rda"]
$ git clone https://github.com/hrbrmstr/rdaradar.git
$ docker build -t rdaradar:0.1.0 -t rdaradar:latest .  
$ docker run --rm -v "$(pwd)/exploit.rda:/unsafe.rda" rdaradar 

Bioconductor

Bioconductor

Papers

How to use Dockerfile

https://docs.docker.com/engine/reference/commandline/build/

The . simply means "current working directory".

docker build -f Dockerfile -t arraytools/myimagename .

docker build -t [myname] .  
# Multiple tags
docker build -t arraytools/biospear:latest -t arraytools/biospear:3.6.0 .

In the above example, we can create the image by

docker image build -t pinger .

We can run a container from the pinger image

docker container run --rm -it pinger

Docker Build Args

How to Use Docker Build Args to Configure Image Builds

"docker buildx build" vs "docker build"

  • docker build is essentially a wrapper or alias for docker buildx build, but it always uses the default builder for backwards compatibility
  • Difference between docker build and docker buildx build - Docker builder documentation, github page.
  • An example FlagPipe Analyst
    • Multi-platform Support (--platform)
    • Output Option (--output=type=docker)

Clean up after failed builds

Cleanup docker images and containers after failed builds

#!/bin/bash
docker rm $(docker ps -aq) \
  docker rmi $(docker images | grep "^<none>" | awk '{print $3}')

ENTRYPOINT and CMD

The advantage of using ENTRYPOINT + CMD (exec form) instead of using CMD alone (shell form) is we can override the CMD part that I have defined in the Dockerfile.

docker container run --rm -it pinger -w 5 127.0.0.1
# ping the loopback for 5 seconds

If we want to overwrite what's defined in the ENTRYPOINT in the Dockerfile, we need to use the --entrypoint parameter.

docker container run --rm -it --entrypoint /bin/sh pinger
# we'll be inside the container. Type exit to leave the container

When we use the shell form, the ENTRYPOINT is have the default value of /bin/sh -c and whatever is the value of CMD will be passed as a string to the shell command.

Temporary failure resolving 'deb.debian.org' when running "docker build"

Add "--net=host" to the docker build command. See Docker build “Could not resolve 'archive.ubuntu.com'” apt-get fails to install anything

Best practices for writing Dockerfiles

Use multi-stage builds

With multi-stage builds, we have a single Dockerfile containing multiple FROM instructions. Each FROM instruction is a new build stage that can easily COPY artifacts from previous stages.

An example from the "Docker Deep Dive" book.

tag after image was built

$ docker tag <imageID> <newName>/<repoName>:<tagName>

About storage drivers

https://docs.docker.com/storage/storagedriver/#sharing-promotes-smaller-images

Privileged versus Root user in Docker

.dockerignore

Using .dockerignore files to build better Docker images

Dockerfile in One Line

FROM ubuntu

Using This simple Dockerfile and the docker command sudo docker build -t scooby_snacks . will result in

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              15.04               2427658c75a1        42 hours ago        117.5 MB
ubuntu              vivid               2427658c75a1        42 hours ago        117.5 MB
ubuntu              vivid-20150218      2427658c75a1        42 hours ago        117.5 MB
ubuntu              utopic-20150211     78949b1e1cfd        42 hours ago        194.4 MB
ubuntu              utopic              78949b1e1cfd        42 hours ago        194.4 MB
ubuntu              14.10               78949b1e1cfd        42 hours ago        194.4 MB
ubuntu              14.04               2d24f826cb16        42 hours ago        188.3 MB
ubuntu              14.04.2             2d24f826cb16        42 hours ago        188.3 MB
ubuntu              trusty              2d24f826cb16        42 hours ago        188.3 MB
ubuntu              trusty-20150218.1   2d24f826cb16        42 hours ago        188.3 MB
ubuntu              latest              2d24f826cb16        42 hours ago        188.3 MB
scooby_snacks       latest              2d24f826cb16        42 hours ago        188.3 MB
ubuntu              precise             1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              precise-20150212    1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              12.04.5             1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              12.04               1f80e9ca2ac3        42 hours ago        131.5 MB
ubuntu              14.04.1             5ba9dab47459        3 weeks ago         188.3 MB
ubuntu              12.10               c5881f11ded9        8 months ago        172.2 MB
ubuntu              quantal             c5881f11ded9        8 months ago        172.2 MB
ubuntu              13.04               463ff6be4238        8 months ago        169.4 MB
ubuntu              raring              463ff6be4238        8 months ago        169.4 MB
ubuntu              13.10               195eb90b5349        8 months ago        184.7 MB
ubuntu              saucy               195eb90b5349        8 months ago        184.7 MB
ubuntu              10.04               3db9c44f4520        10 months ago       183 MB
ubuntu              lucid               3db9c44f4520        10 months ago       183 MB

List all tags of an image

How can I list all tags for a Docker image on a remote registry?

Tag the image with the git commit ID

$ docker build -t REPOS/IMAGE:$(git rev-parse --verify HEAD)

Run a shell script on host

$ docker run -v /path/to/sample_script.sh:/sample_script.sh \
  --rm ubuntu bash sample_script.sh

# GATK container example
# First we log in interactive and see where is the default location (/usr in this case)
$ docker run --rm -i -t broadinstitute/gatk3:3.8-0 bash
$ cat > tmp.sh << EOF
> pwd
> ls
> java -jar GenomeAnalysisTK.jar --version
> EOF
$ docker run --rm -v $(pwd):/usr/my broadinstitute/gatk3:3.8-0 bash my/tmp.sh
# ALTERNATIVELY, WE CAN PUT OUR SCRIPT IN THE TOP DIRECTORY (Hopefully the name is not duplicated)
$ docker run --rm -v $(pwd)/tmp.sh:/tmp.sh broadinstitute/gatk3:3.8-0 bash /tmp.sh
docker run -d -v$(pwd):/my SOMEIMAGE bash 
docker exec -d Test bash /my/script.sh

Link containers together

Manage data in containers

Assign a static IP to a container

Running Multiple Docker Services on the Same Server

How to Run Multiple Docker Containers on Different IP Addresses

Firewall

Rstudio server not loading, taking too long to respond in browser. On Ubuntu run sudo ufw allow PORTNUMBER.

Docker DNS/internet problem in 'docker build' or 'docker run'

I got an error on resolving the debian server when I was creating an image from a Dockerfile that needs to run apt update and apt install commands. See RStudio in Docker – now share your R code effortlessly!. The problem happened on my Linux Mint Desktop but not on a VirtualBox VM (Ubuntu 18.04).

Fix Docker's networking DNS config

A temporary solution is to add the --network=host option to docker build or docker run command.

A permanent solution is to create a new file /etc/docker/daemon.json and include the working DNS server IPs (these are obtained through the nmcli command or the NetworkManager GUI; see Query DNS server).

{
  "dns": ["8.8.8.8", "8.8.4.4"]
}

Then restart the docker service: sudo service docker restart or sudo systemctl restart docker

A quick test on the DNS problem is

docker run --rm busybox nslookup google.com

Working with Docker hub

https://docs.docker.com/userguide/dockerrepos/

Github Actions

Enabling HTTPS/Let's encrypt

Enabling HTTPS by self-sign certificates

traefik: The Cloud Native Application Proxy

Nginx proxy manager

docker: Error response from daemon: Cannot link to /site1_app_1, as it does not belong to the default network.

Running multiple web applications on a Docker host

GUI apps

Firefox example

Running GUI Applications in Docker Container

From ubuntu:20.04
RUN apt update
RUN apt install firefox -y
RUN apt install python3-pip -y
RUN pip3 install  notebook

CMD /usr/bin/firefox
CMD jupyter-notebook --allow-root
nano Dockerfile
docker build -t gui .
docker run --env="DISPLAY" --net=host --name=firefox gui

It works. However, I need to use docker rm -f firefox to kill it since Ctrl+c does not work.

Meld/gedit examples, save a running container as an image

  • How to Run GUI-Based Applications in Docker
    1. Set Up Project Folder and Dockerfile nano dockerGUIFile
    2. Build the Docker Image sudo docker build -t mygedit:1 -f dockerGUIFile .
    3. Launch Docker Container with GUI Support Enabled xhost +local:docker, docker run -it --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix mygedit:1
    4. Disconnect Docker from X Server xhost -local:docker
  • Running a GUI Application in a Docker Container. It works. Below is a modified version for creating the meld app. I can save file modified by meld. To use the app, I need to place files in the ~/Documents/docker (defined in -v). Note that the RAM usage is very minimal. Unfortunately on macOS, I got an error something related to Gtk.
    host> docker image pull ubuntu:jammy  # 22.04
     
    host> docker container run --rm --net host -v /tmp/.X11-unix:/tmp/.X11-unix -it ubuntu:jammy
    container# apt update
    container# apt install -y meld
    host> xhost +local:
    container# export DISPLAY=:0
    
    host> docker container ls  # find the ID of the running container
    host> docker commit <ID> meld
    container# exit
    
    host> docker container run --rm --net host \
      -v /tmp/.X11-unix:/tmp/.X11-unix \
      -v ~/Documents/docker:/meld \
      -e DISPLAY \
      --name=meld \
      meld meld
    

R and httpgd package

  • httpgd Docker vignette, installation from Github.
  • It works. However, currently "httpgs" is archived in CRAN (2023/1/25). So my temporary solution is
    $ docker run --rm -it r-base:4.2.2 bash
    # apt update
    # apt install  libfontconfig1-dev
    # R
    > install.packages("remotes")
    > remotes::install_github("nx10/httpgd")
    ## note if we try to run 'httpgd::hgd(host = "0.0.0.0", port = 8888)', it does not work.
    ## The reason is we have not use "-p" option to expose a port in the previous "docker run" command
    
    ## open another terminal and create a docker image based on the current container
    $ docker ps -a | head
    $ docker commit CONTAINER_ID httpgd:4.2.2
    $ docker run --rm -it -p 8888:8888 httpgd:4.2.2 R
    > httpgd::hgd(host = "0.0.0.0", port = 8888)
    > plot(1:5)
    
  • It works when I tested it on a remote ubuntu server (R 4.4.0 & httpgd 2.0.1) (following the instruction on Docker vignette). Either IP or hostname works but the hostname URL link given by httpgd::hgd() needs to be modified to include .local.
  • Some variation of using hgd()
    hgd(host="0.0.0.0", port = 8888) # allow connection from any one from any computer
    hgd()                # default is host=127.0.0.1, port will be random
    hgd(token="secret")  # define the token
    
    hgd_browse()
    hgd_close()
    hgd_details()
    hgd_url()
    hgd_view()
    
  • To use it with Bioconductor (the Bioconductor docker image will use p3m.dev to install binary R packages so it is fast to create images), we can do like this
    $ docker run --rm -it -p 8888:8888 bioconductor/bioconductor_docker:RELEASE_3_18 R 
    
    > install.packages("httpgd")
    > httpgd::hgd(host = "0.0.0.0", port = 8888)
    

    OR use, for example, "bioconductor/bioconductor_docker:RELEASE_3_18" as the base image in the Dockerfile, and follow the same instruction from httpgd vignette to create a docker image.

    $ nano Dockerfile_httpgd
    $ docker build . -f Dockerfile_httpgd -t bioc-httpgd:RELEASE_3_18
    $ docker images
    $ docker run --rm -it --user rstudio -p 8888:8888 bioc-httpgd:RELEASE_3_18 R
    
  • Singularity. The following is a definition file that is using the bioconductor image + the httpgd package.
    Bootstrap: docker
    From: bioconductor/bioconductor_docker:RELEASE_3_18
    
    %post
        apt-get update \
        && apt-get install -y --no-install-recommends \
        libfontconfig1-dev \
        && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* \
        && install2.r --error --skipinstalled --ncpu -1 \
        httpgd \
        && rm -rf /tmp/downloaded_packages
    
    %runscript
        exec /usr/local/bin/R
    
    %environment
        export LC_ALL=C
    sudo singularity build bioc.sif bioc.def
    singularity run bioc.sif 
    
    > httpgd::hgd(host = "0.0.0.0", port = 8888)

    After we copy the URL, we need to modify the IP or hostname.

Docker-OSX

https://github.com/sickcodes/Docker-OSX

Delete/remove/prune unused resources

Prune unused Docker objects

  • How much disk space is Docker using?
    docker system df  # after calling 'docker buildx prune -f'
    # TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
    # Images          22        14        28.53GB   14.53GB (50%)
    # Containers      15        10        41.01MB   39.58MB (96%)
    # Local Volumes   7         3         1.025GB   223.9MB (21%)
    # Build Cache     60        0         0B        0B
  • Prune build cache if you are using standard Docker builds (seems most effective). Buildx/BuildKit stores intermediate layers and cache objects that are not removed by docker rmi. These can accumulate and take up a lot of space over time.
    docker builder prune
    
    docker system df  # Usually it is more than what Docker reports.
    
    sudo du -sh /var/lib/docker  
    # shows the "actual" space on disk used by the entire Docker data directory, 
    # including: All images, containers, volumes, build cache, metadata, logs, 
    # overlay filesystems, network configs, and possibly orphaned or dangling 
    # data not accounted for by Docker’s internal tracking.
  • Prune build cache if you are using Buildx (for example, with docker buildx build), you should use docker buildx prune to manage its cache.
    docker buildx prune -f
  • Prune containers
    docker container prune # remove all containers that are not in ''running'' status
                           # Docker will ask for confirmation before deleting the containers
    
    docker container prune -f
    docker container rm -f $(docker container ls -aq) # remove even the running containers
  • Prune dangling images: Dangling images are images that aren’t tagged and aren’t referenced by any container. Normal but unused/unreferenced images are kept and won't be deleted. See <none>:<none>images.
    docker image prune # unused image layers

    For example suppose you have created an image locally. If you don't like the new image created by docker build, simply remove it with docker rmi <new_image_name_or_id>. Any base images pulled during the build that are not used by other images can also be removed with: docker image prune.

  • Remove all unused images: If you want to remove all images that aren’t used by any existing containers, you can use the -a flag. It will give a warning saying: this will remove all images without at least one container associated to them. "Exited" container like "hello-world" will not be deleted.
    docker image prune -a

    Used images means anyone shown by docker ps -a.

  • Prune volumes
    docker volume ls
    docker volume prune # unused volumes by at least one container
    
    docker volume prune --filter 'label=demo'
    docker volume prune --filter 'label=demo' --filter 'label=test'
  • Prune networks
    docker network prune
  • Clean up unused docker data. It remove
    • all stopped containers
    • all networks not used by at least one container
    • all dangling images
    • unused build cache
    docker system prune

    (More aggressive) Use docker system prune -a if we want to remove all images without at least one container associated to them.

    (Most aggressive; dangerous): docker system prune -a --volumes if we want to removes everything unused, including anonymous data volumes not used by at least one container.

  • How to identify which Docker container an overlay is for?
    DIRNAME=/var/lib/docker/overlay2
    for CONTAINER in $(docker ps -qa);
        do docker inspect $CONTAINER |grep -q $DIRNAME && docker ps -a |grep $CONTAINER;
    done
    

Plugins

How to Manage Docker Engine Plugins

Misc

LXC (raw Linux containers)

LXC vs Docker

Vagrant vs Docker

Date/Time zone

docker run --rm -t -i -v /etc/localtime:/etc/localtime:ro ubuntu date

Access the internet from the container

Run the container with the '--net=host' option

sudo docker run --net=host -it ubuntu /bin/bash

How to transfer/copy an image to another host

How to copy Docker images from one host to another without using a repository

# Step 1: save the Docker image as a tar file:
docker save -o <path for generated tar file> <image name>

# Step 2: copy your image to a new system with regular file transfer tools such as cp or scp. 

# Step 3: After that you will have to load the image into Docker:
docker load -i <path to image tar file>

The tar file size is the same as what we get from 'docker image'. If we use the 'gzip' utility, it can reduce the file size (e.g 2.7GB to 1.1GB).

Or https://stackoverflow.com/a/39716019

# Step 1:
docker save docker-image-name | gzip > my-image.tar.gz
# Step 3:
docker load < my-image.tar.gz

Where are Docker containers/images stored on the host: /var/lib/docker

The default is /var/lib/docker. The location can be changed by modifying the file /etc/default/docker. Three options if we are tight on the disk space.

1. Create a softlinks for the Docker data directory (/var/lib/docker) and for /var/lib/docker/tmp as described at miscellaneous-options. See this. See for how to stop docker daemon on different OS.

sudo service docker stop   # or sudo systemctl stop docker
sudo mv /var/lib/docker /a/new/location
sudo ln -s /a/new/location /var/lib/docker # Create a symbolic link
sudo service docker start  # or sudo systemctl start docker

2. Change the default location to another place. For example,

sudo nano /etc/default/docker
# Add a line DOCKER_OPTS="-g /home/brb/Docker"

Then after running sudo service docker.io restart and then a simple pull sudo docker pull rocker/r-base or sudo docker run --rm -ti rocker/r-base (the Dockerfile of r-base is available on github.com, --rm option means Automatically remove the container when it exits), we will see something like this:

$ docker run --rm -ti rocker/r-base
$ docker images
$ docker -v
Docker version 1.0.1, build 990021a

$ docker -D info | grep Root
 Root Dir: /home/brb/Docker/aufs

Consuming Docker system events

# Open a new terminal
docker system events
# This command is a blocking command. 
# Thus, when you execute it in your terminal session the according session is blocked.

# Open another terminal
docker container run --rm alpine echo "Hello World"

Monitor tools

Docker Machine

Docker Machine is a tool that lets you

  • Install Docker Engine on virtual hosts. You can use Machine (a unified way) to create Docker hosts on your local Mac or Windows box, on your company network, in your data center, or on cloud providers like Azure, AWS, or Digital Ocean. See the comment on here.
  • Provision and manage multiple remote Docker hosts
  • Provision Swarm clusters

Docker machine is not installed in Linux when you install Docker. See the instruction on here to install it.

My feeling is if we just want to play Docker on a local Linux machine, we don't really need to use Docker Machine (it just make life more complicated). But if we are working on Mac/Windows or we want to work on clouds or test on VirtualBox, we shall use Docker machines.

Use Docker-machine to Create Docker Servers. Compare the Docker images on the local machine (server 1) & a new host (server 2) created by docker-machine. Question: 1. how to tell we are in the host/machine environment? 2. how to exit the host environment after we use eval $() command? docker-machine stop MachineName.

$ docker-machine help
$ docker-machine create --driver=virtualbox test
# Follow its hint on the output, issue the following command
$ docker-machine env test
# Follow its hint on the output, issue the following command
$ eval$(docker-machine env test) # will configure the docker CLI to connect to this docker machine 'test'
                                 # This is equivalent to running 4 export commands on the command line
$ docker-machine ls  # Very useful
$ docker-machine stop test
$ docker-machine ip test
$ docker-machine start test
$ docker-machine rm test

Play Docker Machine on Mac with Virtualbox. Docker can be used to create a virtual machine just like Vagrant.

$ docker-machine create -d virtualbox demo
$ docker-machine ls

# first way to access a Docker host
$ docker-machine ssh demo
docker@demo:~$ docker images # empty for now

# second way to access 
$ docker-machine env demo
$ eval $(docker-machine env demo)
$ docker version

RancherOS demo video used the docker-machine command to pull and run the RancherOS.

docker-machine create -d virtualbox --virtualbox-boot2docker-url https://releases.rancher.com/os/latest/rancheros.iso demo
docker-machine ssh demo
ps
docker ps
sudo system-docker ps

sudo ros help
sudo ros console list
sudo ros console switch ubunu
apt-get help

Package CLI Applications

How to Use Docker to Package CLI Applications

Stack

Docker app

Docker App is an experimental Docker feature which lets you build and publish application stacks consisting of multiple containers. It aims to let you share Docker Compose stacks with the same ease of use as regular Docker containers.

How to Use 'Docker App' to Containerise an Entire Application Stack

Docker Swarm

Security

Moby Project

What is Docker's Moby Project?

Windows container

When Not to Use Docker

When Not to Use Docker: Cases Where Containers Don’t Help

Docker Compose <compose.yaml>

Docker Compose can help us out as it allows us to specify a single file in which we can define our entire environment structure and run it with a single command (much like a Vagrantfile works).

YAML validator

https://codebeautify.org/yaml-validator

Download binary

Difference of "docker compose" and "docker-compose"

  • Docker-compose is the original Python-based command-line tool that was released in 2014. Docker compose is a newer Go-based command-line tool that is integrated into the Docker CLI platform and supports the compose-spec. Docker compose is meant to be a drop-in replacement for docker-compose, but it may have some behavior differences and new features. Docker compose is currently a tech preview, but it will eventually replace docker-compose as the recommended way to use Compose.

Simple examples

Create a file docker-compose.yml and run docker-compose up after creating the file.

hello-world: 9kB

version: "3"
services:
  hello:
    image: hello-world

alpine: 7.73MB

version: "3"
services:
  server:
    image: alpine
    container_name: my_container
    command: sh -c "echo 'hello' && echo 'docker'"

Nginx: 135MB

mkdir src
echo "Hello world!" > src/index.html
version: "3"
services:
  client:
    image: nginx
    ports:
      - 8000:80
    volumes:
      - ./src:/usr/share/nginx/html

Composerize/convert a docker command into a docker compose file

An example from 'Fundamentals of Docker'

git clone https://github.com/fundamentalsofdocker/labs.git
cd labs/ch08
docker-compose up
# Open http://localhost:3000/pet

The images do not show up:( The terminal shows what has happened under the hood. So the problem is the http links for images do not exist.

We can also run the application in the background

docker-compose up -d

To stop and clean up the application, Howto use docker-compose to Start, Stop, Remove Docker Containers

docker-compose down # Stop and remove containers, networks, images, and unnamed volumes
                    # defined in the docker-compose.yml flie
# OR
docker-compose down -v # similar to above but remove named volumes defined in yml file
# OR
docker-compose stop && docker-compose rm -f
docker-compose rm -v

If we also want to remove the volume for the database

docker volume rm ch08_pets-data

An example from "How to Setup NGINX as Reverse Proxy Using Docker"

See here. Only nginx is used.

An example from "Docker Deep Dive" (flask + redis)

Note that on Get started with Docker Compose it mounts the current directory to /code inside the container. So after we modify app.py, we don't need to copy it to the container.

Another one Docker compose tutorial for beginners by example

$ git clone https://github.com/nigelpoulton/counter-app.git
$ cd counter-app
$ ls
app.py  docker-compose.yml  Dockerfile  README.md  requirements.txt

$ cat requirements.txt 
flask

$ cat Dockerfile
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

$ cat docker-compose.yml 
version: "3.5"
services:
  web-fe:
    build: .
    command: python app.py
    ports:
      - target: 5000
        published: 5000
    networks:
      - counter-net
    volumes:
      - type: volume
        source: counter-vol
        target: /code
  redis:
    image: "redis:alpine"
    networks:
      counter-net:

networks:
  counter-net:

volumes:
  counter-vol:

$ docker-compose up &

$ docker container ls

$ docker network ls
NETWORK ID          NAME                     DRIVER              SCOPE
2acef6dabde6        bridge                   bridge              local
a2d42bc482ff        counterapp_counter-net   bridge              local
e1e093b64282        host                     host                local
7ecd0a6a9ebd        none                     null                local

# Open the browser http://localhost:5000
$ docker-compose ps
       Name                      Command               State           Ports         
-------------------------------------------------------------------------------------
counterapp_redis_1    docker-entrypoint.sh redis ...   Up      6379/tcp              
counterapp_web-fe_1   python app.py                    Up      0.0.0.0:5000->5000/tcp

$ docker-compose stop
$ docker-compose ps
# We can see stopping a Compose app does not delete the application

$ docker container ls -a
$ docker-compose rm     # delete a stopped Compose app
                        # images, volumes and source code remain
$ docker-compose restart
                        # If you made changes to your Compose app since stopping,
                        # these changes will not appear in the restarted app.
                        # You need to re-deploy the app to get the changes.
$ docker-compose ps
$ docker-compose down   # stop and delete the app
                        # images, volumes and source code remain
$ docker-compose down --volumes # remove the data volume used by the Redis container
$ docker-compose up -d 
$ docker volume ls
$ docker-compose 

# We can make changes to files in the volume, from the host side,
# and have them reflected immediately in the app.
$ nano app.py   # do some changes
$ docker volume inspect counterapp_counter-vol | grep Mount
$ sudo cp app.py \
  /var/lib/docker/volumes/counterapp_counter-vol/_data/app.py
# Our changes should be reflected 

$ docker-compose --help

Create Compose Files From Running Docker Containers

How to Automatically Create Compose Files From Running Docker Containers

Docker-Compose persistent data MySQL

https://stackoverflow.com/questions/39175194/docker-compose-persistent-data-mysql

Connect to Docker daemon over ssh using docker-compose

#DockerTips: Connect to Docker daemon over ssh using docker-compose

Dockerfile + docker-compose

Docker Compose vs. Dockerfile - which is better?

The Compose file describes the container in its running state, leaving the details on how to build the container to Dockerfiles.

How to deploy on remote Docker hosts with docker-compose

How to deploy on remote Docker hosts with docker-compose

logs

docker-compose logs -f
# Ctrl + c

GUI/TUI interface manager

11 Must-Have Docker Tools To Simplify Your Workflow:

  • LazyDocker - Command-Line Docker Management
  • Dive - Analyze Docker Image Layers
  • Portainer – Simplify Docker Management
  • Watchtower – Automated Docker Container Updates
  • Dockly – Interactive Docker Management Tool
  • Docker Compose – Define and Run Multi-Container Apps
  • Dry – Real-time Docker Container Monitoring
  • Sliplane – Cloud-Based Docker Management Tool
  • Orbstack (closed source) - manage VM and Docker containers
  • Docker Desktop – A Graphical Interface for Docker
  • Visual Studio Code (VS Code) Docker Extension

Dry

Dry – An Interactive CLI Manager For Docker Containers. The TUI is built on top of termui; a cross-platform, easy-to-compile, and fully-customizable terminal dashboard. It is inspired by blessed-contrib, but purely in Go.

LazyDocker (TUI)

Dockly (TUI)

Dockly – Manage Docker Containers From Terminal

DockStation

It is not open source. It works with remote Docker containers.

DockSTARTer: get started with home server apps running in Docker

Portainer* (nice)

IP address 0.0.0.0

How to setup ip address in portainer to access containers?
(Left hand side) Administration -> Environment-related -> Environments > local (or whatever your environment is named) -> Public ip.

Templates

Yacht

cockpit-docker

sudo apt-get -y install cockpit-docker

sudo systemctl restart cockpit

DockerUI (Deprecated, Development continues at Portainer)

https://github.com/kevana/ui-for-docker. A quick start:

  1. Run:
    docker run -d -p 9000:9000 --privileged \
        -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
    where -v means to bind mount a volume.
  2. Open your browser to http://<dockerd host ip>:9000

Note: Anyone in the local network can access the website without any authentication.

Rancher

$ sudo apt-get install ufw
$ sudo ufw allow 4500/udp
$ sudo ufw allow 500/udp
  • discoposse.com
    • Part 1 Installing Rancher and Setting Access Control
    • Part 2 Adding a Docker Host to Rancher
    • Part 3 Adding the DockerHub to our Rancher Registry
    • Part 4 Using the Catalog Example with GlusterFS

Seagull

https://youtu.be/TuT5gb8oRw8

docker run -d -p 127.0.0.1:10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull

The only issue is there is no username/password to protect other people to access the web GUI. The solution of binding to localhost to restrict the access does not work for remote administration.

That is, the tool is suitable for home use.

Kitematic (Mac, Windows and Ubuntu)

Owned by Docker. Available for Mac OS X 10.8+ and Windows 7+ (64-bit) and Ubuntu. https://github.com/docker/kitematic/releases/

Run containers through a simple, yet powerful graphical user interface.

It can not connect to remote docker machines.

A Share your Shiny Apps with Docker and Kitematic!

Shipyard (retired)

VS Code

Applications

Docker Applications

CasaOS

Every app is based on a Docker application

Orchestrator

Kubernete

Kubernete vs Docker swarm

k3s: Lightweight Kubernetes

Run Kubernetes on a Raspberry Pi with k3s

Kubeflow

Other containers

Docker Is Dead — And It's About Time

Podman

  • Podman Installation Instructions
    • How To Install Podman Desktop In Linux
    • Raspberry Pi OS use the standard Debian's repositories, so it is fully compatible with Debian's arm64 repository. You can simply follow the steps for Debian to install Podman.
    • I can install it on office computer (Mac), but running 'podman pull' will give me an error. Your network might be using an SSL inspection proxy that intercepts and re-signs SSL certificates. This proxy effectively becomes the "unknown authority" that signed the certificate. A simple solution is to change to wifi 'guest' network instead of the corporate network.
      $ podman machine init && podman machine start # create VM, needed on mac/Windows
      $ podman pull hello-world
      Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
      Trying to pull quay.io/podman/hello:latest...
      Error: internal error: unable to copy from source docker://quay.io/podman/hello:latest: initializing source docker://quay.io/podman/hello:latest: pinging container registry quay.io: Get "https://quay.io/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
      
      $ podman machine stop
      $ podman machine rm
      $ podman machine list
      
  • Podman vs docker:
    • One of the main differences between Podman and Docker is their architecture. Docker uses a client-server architecture with a central daemon that manages containers. In contrast, Podman is daemonless and uses a fork-exec model to manage containers.
    • Podman is designed to run containers without requiring root privileges or the use of sudo. This is one of the key differences between Podman and Docker, as Docker requires root privileges to run containers.
    • Both Podman and Docker are compatible with the Open Container Initiative (OCI) container specification, which means that they can run the same container images. However, Podman is more closely aligned with Kubernetes and its native container runtime, while Docker also works with its own orchestration tool, Docker Swarm.
    • Podman provides several benefits over Docker. For example, Podman is daemon-less, which means that if the Docker daemon crashes, the containers are in an uncertain state. This is prevented by making Podman daemon-less. You can also use systemd to manage your containers with Podman, which gives you virtually unlimited configurability compared to Docker. Hooking Podman with systemd allows you to update running containers with minimal downtime and recover from any bad updates.
  • Podman is a project from Red Hat
  • Getting Started With Podman Desktop, an Open Source Docker Desktop Alternative
  • Podman Compose - Managing Containers
    pip3 install podman-compose

    But it seems the compatibility is an issue even I tried a small example based on alpine image.

  • Nginx example (works)
    podman run -it --rm -d -p 8080:80 \
      --name web \
      -v /mnt/Podman/site-content:/usr/share/nginx/html \
      docker.io/libary/nginx
  • Podman Desktop 1.0: Local container development made easy.
  • Podman for Docker Users
    • Prerequisites
    • Moving Images from Docker to Podman
    • Creating a Basic Nuxt.js Project
    • Building a Container Image for Your Nuxt.JS Project
    • Push Your Podman Image to Quay.io
    • Run Your Podman Image with Docker
    • Creating Pods
    • Generate a Kubernetes Pod Spec with Podman
    • Create a Kubernetes Cluster with Kind (Optional)
    • Deploying to Kubernetes
  • Podman, Docker and Singularity all support OCI container format images.
  • Docker vs. Podman vs. Singularity: Which Containerization Platform is Best for R Shiny?
  • Why I Ditched Docker for Podman

Use docker images

How do I do "docker run --rm --name rshiny -p 81:3838 rocker/shiny" using podman?

Docker and Podman use completely separate storage systmes:

  • Docker uses /var/lib/docker
  • Podman uses /var/lib/containers (or ~/.local/share/containers for rootless)

Tip: Export from Docker, import to Podman

docker save rocker/shiny:4.4.0 | podman load
# Or 
# docker save rocker/shiny:4.4.0 | gzip > rocker_shiny.tar.gz
# podman load < rocker_shiny.tar.gz
# rm rocker_shiny.tar.gz

podman images

podman run --rm --name rshiny -p 3838:3838 rocker/shiny:4.4.0

podman rmi docker.io/rocker/shiny:4.4.0

Singularity and HPC systems

  • Old URL at singularity.lbl.gov
  • Singularity enables users to have full control of their environment; Singularity containers let users run applications in a Linux environment of their choosing. No 'sudo' is needed in general unless you want to build a container from a recipe.
  • Containers are more like an executable file for you to use
  • Containers are stored under the current location. It does not have a centre location (like /etc/default/docker if we use docker) to store images.
  • Can convert Docker containers to Singularity and run containers directly from Docker Hub
  • These bind points cannot be created unless the path already exists within the container. To ensure access to these storage spaces and remedy bind point errors, create these directories in the %post section of your Bootstrap file.
  • Singularity Hub

Ref:

Comparison of docker and singularity commands:

docker singularity
$ docker pull ubuntu:latest
$ docker pull broadinstitute/gatk3:3.8-0
$ singularity pull docker://ubuntu:latest
$ singularity pull docker://broadinstitute/gatk3:3.8-0
$ docker build -t myname/myapp:latest -f Dockerfile $ singularity build myapp.sif myapp.def
$ docker shell (not exist) $ singularity shell docker://broadinstitute/gatk3-3.8-0
$ singularity shell gatk3-3.8-0.img
> ls # the default location depends on the host system

> ls /usr # this is from the container

$ singularity shell --bind ~/Downloads:/mnt XXX.img
$ singularity shell docker://ubuntu:latest
# container is ephemeral

$ docker run --name test -it ubuntu date

# The next example is similar to 'singularity exec'
$ docker run --rm -i -t \
-v $(pwd):/usr/my_data \
broadinstitute/gatk3:3.8-0 \
bash /usr/my_data/myscript.sh
$ singularity run gatk3-3.8-0.img date
$ docker run --name ubuntu_bash --rm -i -t ubuntu bash
$ docker exec -d ubuntu_bash touch /tmp/execWorks
# Most useful
$ singularity exec gatk3-3.8-0.img java -version
$ singularity exec xxx.img cat /etc/*release
$ singularity exec docker://rocker/tidyverse:latest R
$ singularity exec docker://rocker/tidyverse:latest Rscript myScript.R

Cache

When we run singularity exec docker://rocker/tidyverse:latest R, it will save something in the cache in our system.

It seems to be OK after I manually delete the directory $HOME/.singularity (tested in Biowulf).

RStudio

$ singularity exec docker://rocker/tidyverse:latest R
$ singularity exec docker://rocker/tidyverse:latest Rscript myScript.R

Shifter

Conda

Anaconda

Bioconda

Using docker to install conda (https://conda.io/docs/user-guide/tutorials/index.html)

$ docker run -t -i --name test --net=host ubuntu bash
# apt-get update
# apt-get install -y wget bzip2 python
# wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh
# wget https://repo.continuum.io/archive/Anaconda2-5.1.0-Linux-x86_64.sh
# bash Miniconda2-latest-Linux-x86_64.sh
# bash Anaconda2-5.1.0-Linux-x86_64.sh
# exit

$ docker start test 
$ docker exec -i -t test bash
# conda list  # WORKS!
# conda config --add channels r
# conda config --add channels defaults
# conda config --add channels conda-forge
# conda config --add channels bioconda
# conda install bwa  (Segmentation fault. Core dumped)
# which bwa
/root/anaconda2/bin/bwa
# conda install r   (Only get 3.4.2 but the latest is 3.4.3.)
# conda install bowtie
# bowtie --version
# conda install gatk (https://bioconda.github.io/recipes/gatk/README.html)
   (Due to license restrictions, this recipe cannot distribute and install GATK directly)
   (R is downgraded to 3.2.2:( )
   (Segmentation fault. Core dumped)
# exit
# docker stop test
# docker rm test

Get miniconda image instead of using a Ubuntu image

$ docker pull continuumio/miniconda
$ docker run -i -t continuumio/miniconda /bin/bash
# conda install r   (get 3.4.2)
# conda config --add channels bioconda
# conda install bwa  (OK, no error)
# conda install gatk  (R was downgraded to 3.2.2, install openjdk 8.0.121)
# which gatk
/opt/conda/bin/gatk
# gatk -h
GATK jar file not found. Have you run "gatk-register"?

Issues:

  • R version is not up to date
  • So the problem is installing GATK requires an installation of R and the current R was affected.

CoreOS

Installation

We first boot a liveCD from any OS (CentOS works but Ubuntu 16.04 gave errors). In Virtualbox, we choose 'Red Hat' if we use CentOS.

Once the VM is created. We go to the settings. Create a bridged network or host-only network first (even we can get files from the host without creating a host-only network). Storage: choose CentOS-7.

  1. Get the install script from Github and create <coreos_install.sh> and chmod +x
  2. create <cloud-config.yaml> file which will include ssh_authorized_keys generated from another machine. It should also contain a new token for the cluster from https://discovery.etcd.io/new.
  3. ls -l /dev/sd*
  4. run sudo ./coreos_install.sh -d /dev/sda -C stable -c cloud-config.yaml. It will download the latest stable CoreOS, install to the HD
  5. Don't leave the VM or it will freeze. Issue sudo shutdown -h now once we see the word 'Success' at the last line of the output.
  6. Remove CentOS from the VM storage. Boot the coreOS VM.

The new screen shows corebm1 login with an IP. Go back to another machine and type ssh -i /tmp/CoreOSBM_rsa [email protected]. Inside CoreOS, we can type docker images.

The 'cloud-config.yaml file has to follow the format in https://coreos.com/os/docs/latest/cloud-config.html. Use the online validator https://coreos.com/validate/ to correct. At first I use the file from the youtube video. There is no error coming out when I ran the installation script. But I cannot connect to coreOS. The cloud-config.yaml file I use is (pay attention to '-', double quotes and indent characters)

#cloud-config
#
# set hostname
hostname: CoreBM1

# Set ssh key
ssh_authorized_keys:
  - "ssh-rsa AAAAB3 ..... brb@T3600"

coreos:
  etcd:
    discovery: "https://discovery.etcd.io/d3e95 .... "
# sudo ./installos -d /dev/sda -C stable -c cloud-config.yaml

CoreOS exploration

brb@T3600 /tmp $ ssh -i /tmp/id_rsa [email protected]
Enter passphrase for key '/tmp/id_rsa':
CoreOS stable (1010.6.0)
core@CoreBM1 ~ $
core@CoreBM1 ~ $ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
core@CoreBM1 ~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        1.4G     0  1.4G   0% /dev
tmpfs           1.4G     0  1.4G   0% /dev/shm
tmpfs           1.4G  340K  1.4G   1% /run
tmpfs           1.4G     0  1.4G   0% /sys/fs/cgroup
/dev/sda9        18G   23M   17G   1% /
/dev/sda3       985M  589M  345M  64% /usr
tmpfs           1.4G     0  1.4G   0% /media
/dev/sda1       128M   37M   92M  29% /boot
tmpfs           1.4G     0  1.4G   0% /tmp
/dev/sda6       108M   52K   99M   1% /usr/share/oem
core@CoreBM1 ~ $ free -m
             total       used       free     shared    buffers     cached
Mem:          2713        187       2525          0          9        109
-/+ buffers/cache:         68       2644
Swap:            0          0          0
core@CoreBM1 ~ $ lsb_release -a
-bash: lsb_release: command not found
core@CoreBM1 ~ $ docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
f069f1d21059: Pull complete
ecbeec5633cf: Pull complete
ea6f18256d63: Pull complete
54bde7b02897: Pull complete
Digest: sha256:bbfd93a02a8487edb60f20316ebc966ddc7aa123c2e609185450b96971020097
Status: Downloaded newer image for ubuntu:latest
core@CoreBM1 ~ $ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              0f192147631d        7 days ago          132.7 MB
core@CoreBM1 ~ $

CoreOS cluster discovery

https://coreos.com/os/docs/latest/cluster-discovery.html

etcd

fleet

TryGhost

https://github.com/TryGhost/Ghost

Firecracker

Firecracker: start a VM in less than a second

Self-hosting

Tools and Resources for Self-Hosting

Linux in browser

Resource

Internet

Books

Blogs

Tips/trouble shooting

Play with Docker (PWD)

  • Some applications I've tested.
    • webtop (OK)
    • r-base:3.6.3, r-base:4.1.0, r-base:4.1.1 (OK)
    • r-base:4.1.2, r-base:4.2.0 (ERROR: R_HOME ('/usr/lib/R') not found). Maybe the docker version there is too old.

Alternatives

The 9 Best Docker Alternatives for Container Management

Serverless computing