Docker: Difference between revisions

From 太極
Jump to navigation Jump to search
(44 intermediate revisions by the same user not shown)
Line 69: Line 69:
<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://www.howtoforge.com/tutorial/how-to-install-kubernetes-on-ubuntu/ How to Install and Configure Kubernetes and Docker on Ubuntu 18.04 LTS] </li>
</ul>
</ul>
=== 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]


== Without sudo, Post-installation ==
== Without sudo, Post-installation ==
Line 84: Line 89:
# Log out and log in
# Log out and log in
</pre>
</pre>
== 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? ==
[https://www.reddit.com/r/docker/comments/q21spb/comment/hfi97s4/ Doesn't matter. Your system will stop the container if you update docker.]
== Is there a way to hibernate a docker container ==
* https://stackoverflow.com/a/45170070
* Reference for [https://docs.docker.com/engine/reference/commandline/checkpoint/ docker checkpoint] (This command is experimental)
== Live restore ==
* [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'''.


== Rate limits for GitHub Apps ==
== Rate limits for GitHub Apps ==
Line 113: Line 132:


== Windows ==
== Windows ==
Note many of the information here have not been updated.
Docker can be run on Windows 10 Pro as a native application; see  
Docker can be run on Windows 10 Pro as a native application; see  
* https://docs.docker.com/engine/installation/windows/.
* https://docs.docker.com/engine/installation/windows/.
Line 349: Line 370:


=== WSL2 ===
=== WSL2 ===
[https://poweruser.blog/docker-on-windows-10-without-hyper-v-a529897ed1cc Docker on Windows without Hyper-V]
* [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 ==
== Mac ==
https://docs.docker.com/desktop/mac/
* https://docs.docker.com/desktop/mac/
 
* Alternatives to Docker Desktop for Mac? Rancher is recommended. 2022-06-08
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].
* 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].


== ARM architeture from hub.docker.com ==
== ARM architeture from hub.docker.com ==
Line 562: Line 584:
</pre>
</pre>


== GUI/TUI interface manager ==
== How and Why to Use A Remote Docker Host ==
=== [https://github.com/moncho/dry Dry] ===
* [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.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://www.cloudsavvyit.com/12514/how-docker-contexts-let-you-work-with-multiple-hosts/ How Docker Contexts Let You Work with Multiple Hosts]


=== LazyDocker (TUI) ===
== Backup ==
[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]
* [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?]


It works on ARM devices too.
= Usage =
== Basics, docs, cheatsheet ==
* https://docs.docker.com/articles/basics/
* [https://www.fosstechnix.com/docker-command-cheat-sheet/ 81 Docker Command Cheat Sheet with Description]
* https://coderwall.com/p/2es5jw/docker-cheat-sheet-with-examples
* 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]
* https://hackernoon.com/introduction-to-docker-a7d9e1f6c0b3#.tezit0hkq
* [http://www.cnblogs.com/wanliwang01/p/docker01.html Docker快速入门]
* [http://blog.myplanet.com/docker-the-fun-and-easy-way Docker: The Fun and Easy Way]


=== Dockly (TUI) ===
Note that we need '''sudo''' is needed unless it is on a Mac OS.
[https://www.ostechnix.com/dockly-manage-docker-containers-from-terminal/ Dockly – Manage Docker Containers From Terminal]


=== DockStation ===
If docker cannot find an image, it will try to pull it from its repository.
It is not open source. It works with remote Docker containers.
<pre>
 
$ sudo docker run -it ubuntu /bin/bash
* [https://github.com/DockStation/dockstation DockStation]
Unable to find image 'ubuntu' locally
* [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
Pulling repository ubuntu
* [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
04c5d3b7b065: Download complete
511136ea3c5a: Download complete
c7b7c6419568: Download complete
70c8faa62a44: Download complete
d735006ad9c1: Download complete
root@ec83b3ac878d:/#
</pre>


=== DockSTARTer: get started with home server apps running in Docker ===
{| class="wikitable"
* https://dockstarter.com/
! purpose
* [https://www.makeuseof.com/tag/setup-linux-media-server/ How to Set Up a Linux Media Server in Under One Hour]
! command
 
|-
=== [https://portainer.io/ Portainer]* (nice) ===
| run a container
<ul>
| docker container run -d -p 80:80 httpd
<li>Portainer itself is a docker application. </li>
|-
<li>https://portainer.readthedocs.io/en/stable/deployment.html#manage-a-new-docker-environment. It seems it will portainer 1.24.1 instead of 2.0. So this instruction is outdated!!
| list running cotainer
</li>
| docker container ls
<li>[https://youtu.be/M365jgJ0O2E How to Update Portainer Fast, Simple, and Easy Guide]. docker stop + docker rm + docker rmi + docker run.
|-
</li>
| view logs of Docker container
<li>[https://dbtechreviews.com/2020/08/update-portainer-to-version-2-0-super-easy/ Update Portainer to Version 2.0 – Super Easy!]. When the first time accessing http://localhost:9000, you need to create a password (at least 8 characters long) for the default user "admin".
| docker container logs cranky_cori
{{Pre}}
|-
$ docker volume create portainer_data
| identify Docker container process?
$ docker run -d -p 9000:9000 -p 8000:8000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
| docker container top  cranky_cori
</pre>
|-
* [https://dbtechreviews.com/2020/09/using-application-templates-in-portainer-2-0/ Using Application Templates in Portainer 2.0]
| stop Docker container?
* [https://youtu.be/BwgKd6LohQo Install 80+ Docker Images In Seconds Using This Portainer App Template] (video)
| docker container stop cranky_cori
* [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)
| list stopped or not running Docker containers
* [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]
| docker container ls -a
</li>
|-
</ul>
| start Docker container
* [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?]
| docker container start c46f2e9e4690
* [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!
| remove Docker container
* [https://www.linuxtechi.com/monitor-manage-docker-containers-portainer-part1/ Monitor and Manage Docker Containers with Portainer.io (GUI tool) – Part-1] 2019
| docker container rm cranky_cori
* [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
| list Docker images
** https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/portainer-2.0/Template/template.json (working), [https://github.com/SelfhostedPro/selfhosted_templates Github]
| docker images
** https://raw.githubusercontent.com/nashosted/self-hosted-template/master/template.json (working)
|-
** Alternative: [https://github.com/Taisun-Docker/taisun taisun]
| remove Docker image
* [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]
| docker rmi iman/touch
* [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


=== Yacht ===
=== Restart docker daemon ===
* https://yacht.sh/Installation/yacht/
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.
* [https://youtu.be/KstIS5DstTE Yacht Installed on Docker - Portainer Alternative] (video)
<pre>
 
sudo service docker start
=== cockpit-docker ===
</pre>
* [https://www.hostwinds.com/guide/installing-and-using-cockpit-docker-linux-vps/ Installing And Using Cockpit-Docker]
After that, I can stop and rm the container.
* The default port is 9090.  
* Not useful for manager docker containers.
<pre>
<pre>
sudo apt-get -y install cockpit-docker
sudo docker stop jenkins
 
sudo docker rm jenkins
sudo systemctl restart cockpit
sudo docker ps -a
</pre>
</pre>


=== [https://github.com/crosbymichael/dockerui DockerUI] (Deprecated, Development continues at Portainer)===
=== images vs containers ===
https://github.com/kevana/ui-for-docker. A quick start:
<pre>
# Run:  <syntaxhighlight lang='bash'>
$ sudo docker images
docker run -d -p 9000:9000 --privileged \
REPOSITORY                    TAG                IMAGE ID            CREATED              VIRTUAL SIZE
     -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
iman                          latest              6e0f5644b2fd        About a minute ago  460.4 MB
</syntaxhighlight>  where '''-v''' means to bind mount a volume.
iman/touch                    latest              77b9ac5951c2        4 minutes ago        460.4 MB
# Open your browser to http://<dockerd host ip>:9000
<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


Note: Anyone in the local network can access the website without any authentication.
$ 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$
</pre>


=== Rancher ===
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)
* https://rancher.com/quick-start/. The doc above is not good enough to follow. Search Google for tutorial or get started guide including screenshots.
<pre>
* [https://www.howtoforge.com/tutorial/ubuntu-rancher-docker-container-manager/ How to Manage Docker Containers with Rancher on Ubuntu 16.04]
$ sudo docker rm thirsty_engelbart  # iman/touch
* [https://hackernoon.com/creating-a-scalable-application-using-docker-rancher-rancheros-cattle-5feb83a3e743 Creating A Scalable Application Using Docker + Rancher + RancherOs + Cattle]
$ sudo docker rm dc9e82f2c00a      # eddelbuettel/docker-ubuntu-r:add-r-devel-san
* Initial setup video https://youtu.be/1EMW1y7529Y
$ sudo docker ps -a   # check to see the container is gone now
* Training from Rancher Labs https://youtu.be/8K14A_CZFdI. It seems Rancher is complicated but powerful. The whole operation is like Amazon Cloud.
* [https://gist.github.com/lmmendes/fbed32a452cf02d2a1095658795cb3d2 Running Rancher locally (with two hosts) using MacOS Docker and VirtualBox]
* To allow UDP port
<syntaxhighlight lang='bash'>
$ sudo apt-get install ufw
$ 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


=== [https://github.com/tobegit3hub/seagull Seagull] ===
$ sudo docker rmi 6e0f5644b2fd
https://youtu.be/TuT5gb8oRw8
$ sudo docker rmi iman/touch
$ sudo docker images  # check to see the images are gone now
</pre>


=== Command line interface, CLI ===
https://docs.docker.com/engine/reference/commandline/cli/ Docker command line
<pre>
<pre>
docker run -d -p 127.0.0.1:10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull
$ docker
</pre>


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.
Usage: docker COMMAND


That is, the tool is suitable for home use.
A self-sufficient runtime for containers


=== [https://kitematic.com/ Kitematic] (Mac, Windows and Ubuntu) ===
Options:
Owned by Docker. Available for Mac OS X 10.8+ and Windows 7+ (64-bit) and Ubuntu. https://github.com/docker/kitematic/releases/
      --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


Run containers through a simple, yet powerful graphical user interface.
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


It can not connect to remote docker machines.
Commands:
 
  attach      Attach local standard input, output, and error streams to a running container
A [https://www.r-bloggers.com/share-your-shiny-apps-with-docker-and-kitematic/ Share your Shiny Apps with Docker and Kitematic!]
  build      Build an image from a Dockerfile
 
  commit      Create a new image from a container's changes
=== [https://github.com/shipyard/shipyard Shipyard] (retired) ===
  cp          Copy files/folders between a container and the local filesystem
* [https://www.sumologic.com/blog/code/managing-containers-docker-shipyard/ Managing Containers with Docker Shipyard]
  create      Create a new container
* Three alternatives:
  diff        Inspect changes to files or directories on a container's filesystem
** [http://rancher.com/ Rancher]
  events      Get real time events from the server
** [https://github.com/kevana/ui-for-docker Docker UI]
  exec        Run a command in a running container
** [https://portainer.io/ Portainer]
  export      Export a container's filesystem as a tar archive
 
  history    Show the history of an image
=== VS Code ===
  images      List images
* [https://youtu.be/i7ABlHngi1Q Docker For Beginners: From Docker Desktop to Deployment]
  import      Import the contents from a tarball to create a filesystem image
* [https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers Visual Studio Code Remote - Containers]
  info        Display system-wide information
* [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]
  inspect    Return low-level information on Docker objects
* [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]
  kill        Kill one or more running containers
 
  load        Load an image from a tar archive or STDIN
== How and Why to Use A Remote Docker Host ==
  login      Log in to a Docker registry
* [https://www.cloudsavvyit.com/11185/how-and-why-to-use-a-remote-docker-host/ How and Why to Use A Remote Docker Host]
  logout      Log out from a Docker registry
* [https://www.cloudsavvyit.com/12514/how-docker-contexts-let-you-work-with-multiple-hosts/ How Docker Contexts Let You Work with Multiple Hosts]
  logs        Fetch the logs of a container
 
  pause      Pause all processes within one or more containers
= Usage =
  port        List port mappings or a specific mapping for the container
== Basics, docs, cheatsheet ==
  ps          List containers
* https://docs.docker.com/articles/basics/
  pull        Pull an image or a repository from a registry
* https://www.docker.com/sites/default/files/d8/2019-09/docker-cheat-sheet.pdf
  push        Push an image or a repository to a registry
* https://coderwall.com/p/2es5jw/docker-cheat-sheet-with-examples
  rename      Rename a container
* https://github.com/wsargent/docker-cheat-sheet
  restart    Restart one or more containers
* [https://www.howtoforge.com/tutorial/how-to-use-docker-introduction/ How to use Docker in a practical way]
  rm          Remove one or more containers
* https://hackernoon.com/introduction-to-docker-a7d9e1f6c0b3#.tezit0hkq
  rmi        Remove one or more images
* [http://www.cnblogs.com/wanliwang01/p/docker01.html Docker快速入门]
  run        Run a command in a new container
* [http://blog.myplanet.com/docker-the-fun-and-easy-way Docker: The Fun and Easy Way]
  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


Note that we need '''sudo''' is needed unless it is on a Mac OS.
Run 'docker COMMAND --help' for more information on a command.
</pre>


If docker cannot find an image, it will try to pull it from its repository.
=== Version, system information ===
<pre>
Docker version
$ sudo docker run -it ubuntu /bin/bash
<syntaxhighlight lang='bash'>
Unable to find image 'ubuntu' locally
$ docker version
Pulling repository ubuntu
Client:
04c5d3b7b065: Download complete
Version:          18.06.1-ce
511136ea3c5a: Download complete
API version:       1.38
c7b7c6419568: Download complete
Go version:       go1.10.3
70c8faa62a44: Download complete
Git commit:       e68fc7a
d735006ad9c1: Download complete
Built:             Tue Aug 21 17:24:51 2018
root@ec83b3ac878d:/#
OS/Arch:           linux/amd64
</pre>
Experimental:      false


{| class="wikitable"
Server:
! purpose
  Engine:
! command
  Version:          18.06.1-ce
|-
  API version:      1.38 (minimum version 1.12)
| run a container
  Go version:      go1.10.3
| docker container run -d -p 80:80 httpd
  Git commit:      e68fc7a
|-
  Built:            Tue Aug 21 17:23:15 2018
| list running cotainer
  OS/Arch:          linux/amd64
| docker container ls
  Experimental:    false
|-
</syntaxhighlight>
| 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 ===
System information.
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.
* what mode the Docker engine is operating in (swarm mode or not)
<pre>
* what storage drive is used for the union filesystem
sudo service docker start
* what version of the Linux kernel we have on our host
</pre>
* et al
After that, I can stop and rm the container.
<syntaxhighlight lang='bash'>
<pre>
$ docker system info
sudo docker stop jenkins
Containers: 2
sudo docker rm jenkins
Running: 0
sudo docker ps -a
Paused: 0
</pre>
Stopped: 2
 
Images: 10
=== images vs containers ===
Server Version: 18.06.1-ce
<pre>
Storage Driver: overlay2
$ sudo docker images
Backing Filesystem: extfs
REPOSITORY                    TAG                IMAGE ID            CREATED              VIRTUAL SIZE
Supports d_type: true
iman                          latest              6e0f5644b2fd        About a minute ago  460.4 MB
Native Overlay Diff: true
iman/touch                    latest              77b9ac5951c2        4 minutes ago        460.4 MB
Logging Driver: json-file
<none>                        <none>              aaa75e64ddf0        5 weeks ago          188.3 MB
Cgroup Driver: cgroupfs
ouruser/sinatra                v2                  ea8c9f407a8d        5 weeks ago          447 MB
Plugins:
ubuntu                        14.04              ed5a78b7b42b        5 weeks ago          188.3 MB
Volume: local
ubuntu                        latest              ed5a78b7b42b        5 weeks ago          188.3 MB
Network: bridge host macvlan null overlay
eddelbuettel/docker-ubuntu-r  add-r-devel-san    3c19d078c5d9        3 months ago        460.4 MB
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
hello-world                    latest              ef872312fe1b        4 months ago        910 B
Swarm: inactive
training/sinatra              latest              f0f4ab557f95        8 months ago        447 MB
Runtimes: runc
 
Default Runtime: runc
$ sudo docker ps -a
Init Binary: docker-init
CONTAINER ID IMAGE                                          COMMAND              CREATED        STATUS                  PORTS NAMES
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
8fbdbcdb5126 iman/touch:latest                              "/bin/bash"          2 minutes ago Exited (0) 2 minutes ago      thirsty_engelbart    
runc version: 69663f0bd4b60df09991c08812a60108003fa340
dc9e82f2c00a eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          9 minutes ago  Exited (0) 3 minutes ago      kickass_bardeen   
init version: fec3683
532a90f36aa8 eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        happy_lalande     
Security Options:
7634024ee0bf eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        insane_mclean     
apparmor
14034a9720cb eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          18 hours ago  Exited (0) 18 hours ago        naughty_lumiere   
  seccomp
ca90954628db eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          19 hours ago  Exited (130) 18 hours ago      sick_hawking       
   Profile: default
8bbdcb7c339f eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          19 hours ago  Exited (0) 19 hours ago        modest_davinci     
Kernel Version: 4.15.0-33-generic
e8e24f80f0dd aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      berserk_hodgkin   
Operating System: Ubuntu 18.04.1 LTS
d41959e0eb55 aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      jovial_curie       
OSType: linux
b408c0e2805b aaa75e64ddf0                                  "/bin/sh -c 'apt-get 5 weeks ago    Exited (100) 5 weeks ago      lonely_tesla       
Architecture: x86_64
72a551e4b492 ouruser/sinatra:v2                            "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        jolly_meitner     
CPUs: 4
75fd6cc4658b training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        evil_yalow         
Total Memory: 7.674GiB
cc8886f5a02e training/sinatra:latest                        "/bin/bash"          5 weeks ago    Exited (130) 5 weeks ago      elegant_curie     
Name: t420s
0585e4f5fecd eddelbuettel/docker-ubuntu-r:add-r-devel-san  "/bin/bash"          5 weeks ago    Exited (0) 5 weeks ago        elated_euclid     
ID: VLWB:6BN3:U7KB:L4T4:GQIB:54F3:YZKJ:PAIR:HEUM:UQIC:XLZU:3IFJ
brb@brbweb4:~/Downloads$
Docker Root Dir: /var/lib/docker
</pre>
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


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)
WARNING: No swap limit support
<pre>
</syntaxhighlight>
$ 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
=== List resource consumption ===
$ sudo docker rmi iman/touch
<syntaxhighlight lang='bash'>
$ sudo docker images # check to see the images are gone now
$ docker system df
</pre>
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
</syntaxhighlight>


=== Command line interface, CLI ===
== [https://www.youtube.com/watch?v=umJYDAYxZys A brief intro to docker virtualization] ==
https://docs.docker.com/engine/reference/commandline/cli/ Docker command line
<pre>
<pre>
$ docker
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


Usage: docker COMMAND
cat /etc/redhat-release
yum
cd /home
touch temp.txt
ls
exit


A self-sufficient runtime for containers
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


Options:
ls /home
      --config string      Location of client config files (default "/home/brb/.docker")
exit
  -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:
docker ps -a
  config      Manage Docker configs
docker rm c85850ed0e13 # delete the container
  container   Manage containers
</pre>
  image      Manage images
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.
  network    Manage networks
<pre>
  node        Manage Swarm nodes
sudo docker exec -i -t c85850ed0e13 bash #by ID
  plugin      Manage plugins
or
  secret      Manage Docker secrets
$ sudo docker exec -i -t loving_heisenberg bash #by Name
  service    Manage services
</pre>
  swarm      Manage Swarm
 
  system      Manage Docker
== docker pull ==
  trust      Manage trust on Docker images
https://docs.docker.com/engine/reference/commandline/pull/
  volume      Manage volumes


Commands:
<syntaxhighlight lang='bash'>
  attach      Attach local standard input, output, and error streams to a running container
$ docker pull ubuntu:zesty
  build      Build an image from a Dockerfile
$ docker run -ti --rm ubuntu:zesty /bin/bash
  commit      Create a new image from a container's changes
# lsb_release -a        
  cp          Copy files/folders between a container and the local filesystem
bash: lsb_release: command not found
  create      Create a new container
# cat /etc/*release
  diff        Inspect changes to files or directories on a container's filesystem
DISTRIB_ID=Ubuntu
  events      Get real time events from the server
DISTRIB_RELEASE=17.04
  exec        Run a command in a running container
DISTRIB_CODENAME=zesty
  export      Export a container's filesystem as a tar archive
DISTRIB_DESCRIPTION="Ubuntu 17.04"
  history    Show the history of an image
NAME="Ubuntu"
  images      List images
VERSION="17.04 (Zesty Zapus)"
  import      Import the contents from a tarball to create a filesystem image
ID=ubuntu
  info        Display system-wide information
ID_LIKE=debian
  inspect    Return low-level information on Docker objects
PRETTY_NAME="Ubuntu 17.04"
  kill        Kill one or more running containers
VERSION_ID="17.04"
  load        Load an image from a tar archive or STDIN
HOME_URL="https://www.ubuntu.com/"
  login      Log in to a Docker registry
SUPPORT_URL="https://help.ubuntu.com/"
  logout      Log out from a Docker registry
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
  logs        Fetch the logs of a container
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
  pause      Pause all processes within one or more containers
VERSION_CODENAME=zesty
  port        List port mappings or a specific mapping for the container
UBUNTU_CODENAME=zesty
  ps          List containers
</syntaxhighlight>
  pull       Pull an image or a repository from a registry
 
  push        Push an image or a repository to a registry
=== Update/upgrade images ===
  rename      Rename a container
* 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>'''.
  restart    Restart one or more containers
* [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]
  rm          Remove one or more containers
* 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.
  rmi        Remove one or more images
* [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]
  run         Run a command in a new container
* [https://vsupalov.com/docker-latest-tag/ What's Wrong With The Docker :latest Tag?] '''Do not run any container with the latest tag.'''
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
* [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.
  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.
=== <none>:<none> images ===
</pre>
* [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]


=== Version, system information ===
== Exit/detach from a container without stopping it ==
Docker version
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
$ docker version
$ docker container run -it ubuntu:latest /bin/bash
Client:
# Ctrl+p, Ctrl+q to exit the container without terminating it
Version:          18.06.1-ce
$ docker ps -a # showing the container 70c5aceb5512 is running in the background
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:
# You can reattach your terminal to it with the "docker container exec" command
Engine:
$ docker container exec -it 70c5aceb5512 bash
  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>
</syntaxhighlight>


System information.  
== How to start a stopped Docker container with a different command ==
* what mode the Docker engine is operating in (swarm mode or not)
[https://stackoverflow.com/a/39329138 How to start a stopped Docker container with a different command?]
* what storage drive is used for the union filesystem
 
* what version of the Linux kernel we have on our host
== Clean shutdown DOCKER containers before reboot ==
* et al
* [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'''  
<syntaxhighlight lang='bash'>
* [https://linuxhandbook.com/docker-stop-container/ How to Stop Docker Containers] '''docker ps -q | xargs docker stop'''
$ docker system info
 
Containers: 2
== Dockerizing Applications/Detached mode ==
Running: 0
<pre>
Paused: 0
$ sudo docker run -d --name insane_babbage ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
Stopped: 2
$ sudo docker ps -l
Images: 10
$ sudo docker logs insane_babbage
Server Version: 18.06.1-ce
$ sudo docker stop insane_babbage
Storage Driver: overlay2
$ sudo docker ps
Backing Filesystem: extfs
</pre>
Supports d_type: true
The -d flag tells Docker to run the container and put it in the background, to daemonize it.
Native Overlay Diff: true
 
Logging Driver: json-file
According to https://docs.docker.com/engine/reference/run/#detached-vs-foreground,  
Cgroup Driver: cgroupfs
'''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.'''
Plugins:
 
Volume: local
=== Automatically restart after reboot ===
Network: bridge host macvlan null overlay
https://stackoverflow.com/questions/18786054/how-to-auto-restart-a-docker-container-after-a-reboot-in-coreos
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
 
Swarm: inactive
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
Runtimes: runc
* https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart
Default Runtime: runc
* https://docs.docker.com/engine/admin/start-containers-automatically/#restart-policy-details
Init Binary: docker-init
 
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
<syntaxhighlight lang='bash'>
runc version: 69663f0bd4b60df09991c08812a60108003fa340
$ docker run -d --restart always myCustomeDocker
init version: fec3683
 
Security Options:
$ docker container run --name neverdie -it --restart always ubuntu /bin/bash
  apparmor
# exit
seccomp
$ docker ps -a  # the container is still ther
  Profile: default
$ docker stop neverdie
Kernel Version: 4.15.0-33-generic
$ docker ps -a
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>


=== List resource consumption ===
== Working with Containers ==
<syntaxhighlight lang='bash'>
<pre>
$ docker system df
$ sudo docker run -i -t ubuntu /bin/bash
TYPE                TOTAL              ACTIVE              SIZE                RECLAIMABLE
$ sudo docker version
Images              10                  2                  2.58GB              1.519GB (58%)
$ sudo docker
Containers         2                  0                  304B                304B (100%)
$ sudo docker attach --help
Local Volumes      2                  0                  314.7MB            314.7MB (100%)
</pre>
Build Cache        0                  0                  0B                  0B
 
=== 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]


$ docker system df -v  # more detailed information
=== Alpine image ===
# We can use the information to clean up our system
* [https://www.makeuseof.com/alpine-linux-explained/ Alpine Linux: A Breath of Fresh Mountain Air for Linux Experts]
* [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>
</syntaxhighlight>


== [https://www.youtube.com/watch?v=umJYDAYxZys A brief intro to docker virtualization] ==
=== Running a Web Application ===
<pre>
<pre>
docker search --help
$ sudo docker run -d -P training/webapp python app.py
docker search redis
</pre>
docker search -s 100 redis
 
docker pull --help
Alpine linux is 6MB. It is a good OS to run a web application. See the demo [https://youtu.be/BFKNwr_wllc here].
docker pull ubuntu # download all versions of ubuntu
 
docker images    # available local container images
=== Viewing our Web Application Container ===
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
</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>
<pre>
sudo docker exec -i -t c85850ed0e13 bash #by ID
$ sudo docker ps -l
or
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
$ sudo docker exec -i -t loving_heisenberg bash #by Name
</pre>
</pre>


== docker pull ==
=== Check container status (docker status) - CPU, Memory usage ===
https://docs.docker.com/engine/reference/commandline/pull/
<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]
<pre>
docker stats
</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 pull ubuntu:zesty
$ docker network create MyNewNetworkName
$ docker run -ti --rm ubuntu:zesty /bin/bash
$ docker network ls
# lsb_release -a       
NETWORK ID          NAME                DRIVER              SCOPE
bash: lsb_release: command not found
abae0010bf2c        MyNewNetworkName    bridge              local
# cat /etc/*release
bf4e73473028        bridge              bridge              local
DISTRIB_ID=Ubuntu
7dac0804bc33        host                host                local
DISTRIB_RELEASE=17.04
dbe7f0daef6d        none                null                local
DISTRIB_CODENAME=zesty
$ docker network remove MyNewNetworkName
DISTRIB_DESCRIPTION="Ubuntu 17.04"
# OR docker network rm MyNewNetworkName
NAME="Ubuntu"
</syntaxhighlight>
VERSION="17.04 (Zesty Zapus)"
<li>https://youtu.be/Ox5mZBwc92E
ID=ubuntu
<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]
ID_LIKE=debian
<li>[https://dev.to/leandronsp/mastering-the-docker-networking-2h57 Mastering the Docker networking]
PRETTY_NAME="Ubuntu 17.04"
</ul>
VERSION_ID="17.04"
 
HOME_URL="https://www.ubuntu.com/"
=== [https://docs.docker.com/network/host/ Host network] ===
SUPPORT_URL="https://help.ubuntu.com/"
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.
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
 
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
=== ping, ifconfig and ip commands not found in Ubuntu container ===
VERSION_CODENAME=zesty
<syntaxhighlight lang='bash'>
UBUNTU_CODENAME=zesty
apt update
apt install iputils-ping  # ping
apt install net-tools    # ifconfig
apt install iproute2      # ip
</syntaxhighlight>
</syntaxhighlight>


=== Update/upgrade images ===
=== Network Port Shortcut ===
* 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>'''.
<pre>
* [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 port nostalgic_morse 5000
* 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.
</pre>
* [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.'''
=== Access Ports on the Host from a Docker Container ===
[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]


=== <none>:<none> images ===
=== Multiple NICs ===
* [http://www.projectatomic.io/blog/2015/07/what-are-docker-none-none-images/ What are Docker <none>:<none> images? ]
[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]
* [https://docs.docker.com/engine/reference/commandline/images/#filtering docker images]


== Exit/detach from a container without stopping it ==
=== Viewing the Web Application's Logs ===
<syntaxhighlight lang='bash'>
<pre>
$ docker container run -it ubuntu:latest /bin/bash
$ sudo docker logs -f nostalgic_morse
# Ctrl+p, Ctrl+q to exit the container without terminating it
</pre>
$ 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
=== Clear Logs of Running Docker Containers ===
$ docker container exec -it 70c5aceb5512 bash
[https://www.howtogeek.com/devops/how-to-clear-logs-of-running-docker-containers/ How to Clear Logs of Running Docker Containers]
</syntaxhighlight>


== How to start a stopped Docker container with a different command ==
=== Looking at our Web Application Container's processes ===
[https://stackoverflow.com/a/39329138 How to start a stopped Docker container with a different command?]
 
== Dockerizing Applications/Detached mode ==  
<pre>
<pre>
$ sudo docker run -d --name insane_babbage ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
$ sudo docker top nostalgic_morse
$ 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.


According to https://docs.docker.com/engine/reference/run/#detached-vs-foreground, 
=== Inspecting our Web Application Container ===
'''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.'''
<syntaxhighlight lang='bash'>
$ sudo docker inspect nostalgic_morse
</syntaxhighlight>


=== Automatically restart after reboot ===
=== Obtain the container's IP address, log into a running server ===
https://stackoverflow.com/questions/18786054/how-to-auto-restart-a-docker-container-after-a-reboot-in-coreos
PS. '''Portainer''' web interface can show the IP addresses.  
 
<syntaxhighlight lang='bash'>
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 inspect <container id> | grep "IPAddress"
* https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart
</syntaxhighlight>
* https://docs.docker.com/engine/admin/start-containers-automatically/#restart-policy-details


We don't need the IP address if we just want to log into a running server,
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
$ docker run -d --restart always myCustomeDocker
$ docker exec -it <contianer id> bash
</syntaxhighlight>


$ docker container run --name neverdie -it --restart always ubuntu /bin/bash
=== How to Secure Docker’s TCP Socket ===
# exit
[https://www.cloudsavvyit.com/15079/how-to-secure-dockers-tcp-socket-with-tls/ How to Secure Docker’s TCP Socket with TLS]
$ docker ps -a  # the container is still ther
$ docker stop neverdie
$ docker ps -a
</syntaxhighlight>


== Working with Containers ==
=== 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
<pre>
docker start XXXXXXXX    # restart it in the background
docker attach XXXXXXXX  # reattach the terminal & stdin
</pre>
If we want the latest created container, then we use
<pre>
<pre>
$ sudo docker run -i -t ubuntu /bin/bash
docker start `docker ps -q -l` && docker attach `docker ps -q -l`
$ sudo docker version
$ sudo docker
$ sudo docker attach --help
</pre>
</pre>


=== Environment variables ===
=== docker exec: SSH into a running container ===
* [https://www.baeldung.com/ops/docker-container-environment-variables Passing Environment Variables to Docker Containers]
Run a command in a running container
* [https://docs.docker.com/compose/environment-variables/ Environment variables in Compose]
 
* An example: [https://github.com/tcardonne/docker-github-runner Docker github runner]
* [https://docs.docker.com/engine/reference/commandline/exec/ Usage]: <syntaxhighlight lang='bash'>
 
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
=== Alpine image ===
* [https://www.makeuseof.com/alpine-linux-explained/ Alpine Linux: A Breath of Fresh Mountain Air for Linux Experts]
* [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>
</syntaxhighlight>
* Examples: <syntaxhighlight lang='bash'>
$ docker exec -d ubuntu_bash touch /tmp/execWorks # do st in the background


=== Running a Web Application ===
$ docker exec -it ubuntu_bash bash
<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].
$ docker exec -it -e VAR=1 ubuntu_bash bash # set an environment variable


=== Viewing our Web Application Container ===
$ docker exec -it ubuntu_bash pwd
<pre>
$ docker exec -it -w /root ubuntu_bash pwd # change the working directory
$ sudo docker ps -l
</syntaxhighlight>
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
* [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]
</pre>


=== Check container status (docker status) - CPU, Mem usage ===
=== docker cp ===
[https://github.com/ColinFay/dockerstats docker stats]
* https://docs.docker.com/engine/reference/commandline/cp/
* https://linuxhandbook.com/docker-cp-example/


=== Container networking===
Copy files/folders between a container and the local filesystem.
* 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'>
$ 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>
* https://youtu.be/Ox5mZBwc92E


=== [https://docs.docker.com/network/host/ Host network] ===
=== Restart an exited Container ===
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.
* https://docs.docker.com/engine/reference/commandline/start/
* https://www.linuxnix.com/docker-start-exited-container/
<pre>
$ docker start nostalgic_morse
OR
$ docker restart nostalgic_morse
</pre>
For an interactive container, use '''docker start -ai CONTAINER''' which is equal to run "docker start CONTAINER" and "docker attach CONTAINER".


=== ping, ifconfig and ip commands not found in Ubuntu container ===
=== Rename a container ===
<syntaxhighlight lang='bash'>
[https://docs.docker.com/engine/reference/commandline/container_rename/ docker container rename]
apt update
apt install iputils-ping  # ping
apt install net-tools    # ifconfig
apt install iproute2      # ip
</syntaxhighlight>
 
=== Network Port Shortcut ===
<pre>
<pre>
$ sudo docker port nostalgic_morse 5000
docker container rename CONTAINER NEW_NAME
</pre>
</pre>


=== Access Ports on the Host from a Docker Container ===
=== Inspect container images and their metadata ===
[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]
* [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]
* [https://microbadger.com/images/rocker/r-base MicroBadger]


=== Viewing the Web Application's Logs ===
=== Know the container size ===
<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 ps -s
</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.


=== Obtain the container's IP address, log into a running server ===
=== Removing our Web Application Container ===
PS. '''Portainer''' web interface can show the IP addresses.
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
$ docker inspect <container id> | grep "IPAddress"
$ sudo docker stop nostalgic_morse
$ sudo docker rm nostalgic_morse
</syntaxhighlight>
</syntaxhighlight>


We don't need the IP address if we just want to log into a running server,
Note: Always remember that deleting a container is final!
<syntaxhighlight lang='bash'>
$ docker exec -it <contianer id> bash
</syntaxhighlight>


=== How to Secure Docker’s TCP Socket ===
=== Dockerize an SSH service ===
[https://www.cloudsavvyit.com/15079/how-to-secure-dockers-tcp-socket-with-tls/ How to Secure Docker’s TCP Socket with TLS]
https://docs.docker.com/engine/examples/running_ssh_service/#environment-variables


=== docker attach ===
=== Remove old docker containers ===
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
[http://stackoverflow.com/questions/17236796/how-to-remove-old-docker-io-containers This post] on stackoverflow.com.
<pre>
<pre>
docker start XXXXXXXX    # restart it in the background
$ sudo docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs --no-run-if-empty sudo docker rm
docker attach XXXXXXXX  # reattach the terminal & stdin
</pre>
</pre>
If we want the latest created container, then we use
 
Similarly to remove all exited containers
<pre>
<pre>
docker start `docker ps -q -l` && docker attach `docker ps -q -l`
$ sudo docker ps -a | grep Exit | awk '{print $1}' | xargs sudo docker rm
</pre>
</pre>


=== docker exec: SSH into a running container ===
To kill/stop (not delete) all running containers
Run a command in a running container
<pre>
$ sudo docker kill $(sudo docker ps -q)
</pre>


* [https://docs.docker.com/engine/reference/commandline/exec/ Usage]: <syntaxhighlight lang='bash'>
'''To delete all stopped containers'''
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
<pre>
</syntaxhighlight>
$ sudo docker rm $(sudo docker ps -a -q)
* Examples: <syntaxhighlight lang='bash'>
OR
$ docker exec -d ubuntu_bash touch /tmp/execWorks # do st in the background
$ sudo docker rm `sudo docker ps -a -q`
</pre>


$ docker exec -it ubuntu_bash bash
It is also helpful to create bash aliases for these commands by editing ~/.bash_aliases file.


$ docker exec -it -e VAR=1 ubuntu_bash bash # set an environment variable
=== 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 [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>
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    assaflavie/runlike -p CONTAINER_NAME
</pre>
The '''-p''' option splits the output into pretty lines.


$ docker exec -it ubuntu_bash pwd
=== docker run -it and -d together ===
$ docker exec -it -w /root ubuntu_bash pwd # change the working directory
* [https://stackoverflow.com/a/41918607 Practically, what is the difference between docker run -dit(-itd) vs docker run -d?]
</syntaxhighlight>
* [https://github.com/docker/docker.github.io/issues/10632 "docker run -dit" vs "docker run -d" #10632]
* [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]


=== docker cp ===
=== How to Modify the Configuration of Running Docker Containers ===
* https://docs.docker.com/engine/reference/commandline/cp/
[https://www.cloudsavvyit.com/15254/how-to-modify-the-configuration-of-running-docker-containers/ How to Modify the Configuration of Running Docker Containers]
* https://linuxhandbook.com/docker-cp-example/  


Copy files/folders between a container and the local filesystem.
== Volume ==
* https://docs.docker.com/storage/volumes/
* [https://docs.docker.com/engine/reference/commandline/volume_create/ docker volume create] documentation
* 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.
* [https://www.melvinvivas.com/using-docker-data-volume-with-a-mysql-container/ Using Docker Data Volume with a MySQL container]
* [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?]


=== Restart an exited Container ===
=== Examples of host's volume locations ===
* https://docs.docker.com/engine/reference/commandline/start/
* https://www.linuxnix.com/docker-start-exited-container/
<pre>
<pre>
$ docker start nostalgic_morse
/home/$USER/docker/$PROJECT/$SUB-DIRECTORY
OR
$ docker restart nostalgic_morse
</pre>
</pre>
For an interactive container, use '''docker start -ai CONTAINER''' which is equal to run "docker start CONTAINER" and "docker attach CONTAINER".


=== Inspect container images and their metadata ===
=== Two ways to achieve persistent 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]
* [https://codeblog.dotsandbrackets.com/persistent-data-docker-volumes/ Persistent data in Docker volumes]
* [https://microbadger.com/images/rocker/r-base MicroBadger]
* [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'''.


=== Know the container size ===
=== Inspect the 'Mountpoint' of a volume ===
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker ps -s
$ docker volume create crv
</syntaxhighlight>
$ docker volume ls
[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.


=== Removing our Web Application Container ===
$ docker run -d \
<syntaxhighlight lang='bash'>
    --name mycloud \
$ sudo docker stop nostalgic_morse
    -p 81:80 \
$ sudo docker rm nostalgic_morse
    -v apps:/var/www/html/custom_apps \
</syntaxhighlight>
    nextcloud


Note: Always remember that deleting a container is final!
# docker inspect is not quite useful. It does not show how the volume was created
 
# But we can examine (ls, du, ...) the directory contents
=== Dockerize an SSH service ===
$ docker inspect apps 
https://docs.docker.com/engine/examples/running_ssh_service/#environment-variables
[
    {
        "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 old docker containers ===
=== Remove an an unnamed volume ===
[http://stackoverflow.com/questions/17236796/how-to-remove-old-docker-io-containers This post] on stackoverflow.com.
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.
<pre>
$ 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
<syntaxhighlight lang='bash'>
<pre>
docker rm -v container_name
$ sudo docker ps -a | grep Exit | awk '{print $1}' | xargs sudo docker rm
</syntaxhighlight>
</pre>


To kill/stop (not delete) all running containers
If the volume is named, it stays present. To remove a named volume, use '''docker volume rm volume_name''' .
<pre>
$ sudo docker kill $(sudo docker ps -q)
</pre>


'''To delete all stopped containers'''
=== [https://docs.docker.com/storage/volumes/#start-a-container-with-a-volume Start a container with a volume] ===
<pre>
{| class="wikitable"
$ sudo docker rm $(sudo docker ps -a -q)
! --mount
OR
! -v
$ sudo docker rm `sudo docker ps -a -q`
|-
</pre>
| 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'''.


It is also helpful to create bash aliases for these commands by editing ~/.bash_aliases file.
=== 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.


=== docker create vs docker run ===
<syntaxhighlight lang='bash'>
https://stackoverflow.com/questions/37744961/docker-run-vs-create
# 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",


'''docker create''' is similar to '''docker run -d''' except the container is never started.
# 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


=== Retrieve docker run command ===
# Remove volumes
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].
docker volume rm my-data # Or
<pre>
docker volume rm $(docker volume ls -q)
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    assaflavie/runlike CONTAINER_NAME
</pre>


=== How to Modify the Configuration of Running Docker Containers ===
# Remove all running containers to clean up the system,
[https://www.cloudsavvyit.com/15254/how-to-modify-the-configuration-of-running-docker-containers/ How to Modify the Configuration of Running Docker Containers]
docker rm -f $(docker ls -aq)
</syntaxhighlight>


== Volume ==
=== Sharing data between containers ===
* https://docs.docker.com/storage/volumes/
[https://www.cloudsavvyit.com/15112/how-to-share-data-between-docker-containers/ How to Share Data Between Docker Containers]
* [https://docs.docker.com/engine/reference/commandline/volume_create/ docker volume create] documentation
* 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.
* [https://www.melvinvivas.com/using-docker-data-volume-with-a-mysql-container/ Using Docker Data Volume with a MySQL container]
* [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?]


=== Two ways to achieve persistent data ===
<syntaxhighlight lang='bash'>
* [https://codeblog.dotsandbrackets.com/persistent-data-docker-volumes/ Persistent data in Docker volumes]
docker run -it --name writer -v shared-data:/data alpine /bin/sh
* [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'''.
# 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>


=== Inspect the 'Mountpoint' of a volume ===
=== 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'>
<syntaxhighlight lang='bash'>
$ docker volume create crv
docker run -it --name test -v $(pwd)/src:/app/src alpine /bin/sh
$ docker volume ls


$ docker run -d \
# Make a sample to demonstrate how that works
    --name mycloud \
mkdir ~/my-web; cd ~/my-web
    -p 81:80 \
echo "<h1>My website</h1>" > index.html
    -v apps:/var/www/html/custom_apps \
    nextcloud


# docker inspect is not quite useful. It does not show how the volume was created
# Create 'Dockerfile'
# But we can examine (ls, du, ...) the directory contents
echo -e 'FROM nginx:alpine
$ docker inspect apps 
COPY . /usr/share/nginx/html' > Dockerfile
[
    {
        "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 ===
docker image build -t my-website:1.0 .
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 run -d -p 8080:80 --name my-site my-website:1.0


<syntaxhighlight lang='bash'>
# Open http://localhost:8080. It looks good
docker rm -v container_name
# 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>
</syntaxhighlight>


If the volume is named, it stays present. To remove a named volume, use '''docker volume rm volume_name''' .
=== Define volumes in images ===
 
A few samples of volume definition
=== [https://docs.docker.com/storage/volumes/#start-a-container-with-a-volume Start a container with a volume] ===
<pre>
{| class="wikitable"
VOLUME /app/data
! --mount
VOLUME /app/data, /app/profiles, /app/config
! -v
VOLUME {"/app/data", "/app/profiles", "/app/config"]
|-
</pre>
| docker run -d \
The first line defines a single volume to be mounted at ''/app/data''.
--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'''.
 
=== 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.


We can use the ''docker image inspect'' command to get information about the volumes defined in the Dockerfile.
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
# Create a volume
docker image pull mongo:3.7
docker volume create my-data
docker image inspect --format='{{json .ContainerConfig.Volumes}}' \
docker volume inspect my-data
      mongo:3.7 | jq
# The host folder can be found in the output under 'Mountpoint'
# {
# In my case,
#   "/data/configdb": {},
#       "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
"/data/db": {}
# }


# Mount a volume into a container
# now run an instance of MongoDB and inspect the volume information
docker run --name test -it -v my-data:/data alpine /bin/sh
docker run --name my-mongo -d mongo:3.7
# cd /data
docker inspect --format '{{json .Mounts}}' my-mongo | jq
# echo 'some data' > data.txt
# [
# echo 'more data' > data2.txt
# {
# exit
#   "Type": "volume",
docker inspect my-data
#   "Name": "535e0138b9a32e89f71380e9e73bb0de64ce0d1cad78fcda0ec1d49e11d76d7a",
sudo ls /var/lib/docker/volumes/my-data/_data
#    "Source": "/var/lib/docker/volumes/535e0138b9a32e89f71380e9e73bb0de64ce0d1.../_data",
# We can even try to output the content of say, the second file:
#   "Destination": "/data/configdb",
sudo cat /var/lib/docker/volumes/my-data/_data/data2.txt
#    "Driver": "local",
# We can create a new file in this folder from the host and then use the volume with another container
#    "Mode": "",
echo "the file is created on host" > sudo tee /var/lib/docker/volumes/my-data/_data/host-data
#    "RW": true,
# Let's delete the test container and run another one
#    "Propagation": ""
docker rm test
#  },
# {
#    "Type": "volume",
# SKIP
</syntaxhighlight>


# This time we are mounting our volume to a different container folder
=== Differences between VOLUME and '-v|--volume' ===
docker run --name test2 -it -v my-data:/app/data centos:7 /bin/bash
https://stackoverflow.com/a/25312719
# We are able to see three files:
# ls /app/data


# Remove volumes
=== Container Memory Limits, Setting Available CPUs, Allocating memory and CPU ===
docker volume rm my-data # Or
* [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]
docker volume rm $(docker volume ls -q)
: <syntaxhighlight lang='bash'>
 
docker run \
# Remove all running containers to clean up the system,
    -rm \ ## Automatically remove the container when it exits
docker rm -f $(docker ls -aq)
    --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>
</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]


=== Sharing data between containers ===
== Work with container images ==
[https://www.cloudsavvyit.com/15112/how-to-share-data-between-docker-containers/ How to Share Data Between Docker Containers]
* 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
 
# by name
docker images --format "{{.ID}}\t{{.Size}}\t{{.Repository}}" | sort -k 3
</pre>
 
=== List specific columns ===
<pre>
docker images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}'
</pre>


=== Create an image interactively using '''commit''' - Example 1 ===
The example is from the book 'Learn Docker - Fundamentals of Docker 18.x'.
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker run -it --name writer -v shared-data:/data alpine /bin/sh
docker container run -it --name sample alpine /bin/sh
# create a file inside it
# apk update && apk add iputils
# echo 'my sample file' > /data/sample.txt
# ping 127.0.0.1
# exit
# exit
docker run -it --name reader -v shared-data:/app/data:ro ubuntu:17.04 /bin/bash
docker container ls -a | grep sample
# ls -l /app/data
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>
</syntaxhighlight>


=== Using host volumes ===
If we want to see how our custom image has been built, we can use the ''history'' command as follows:
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 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
</syntaxhighlight>
The first layer in the preceding list is the one we just created by adding the iputils package.


# Make a sample to demonstrate how that works
=== Create an image interactively using '''commit''' - Example 2 ===
mkdir ~/my-web; cd ~/my-web
* [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.
echo "<h1>My website</h1>" > index.html
* [http://www.techrepublic.com/article/how-to-commit-changes-to-a-docker-image/ How to commit changes to a docker image]


# Create 'Dockerfile'
<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.
echo -e 'FROM nginx:alpine
COPY . /usr/share/nginx/html' > Dockerfile


docker image build -t my-website:1.0 .
<syntaxhighlight lang='bash'>
docker run -d -p 8080:80 --name my-site my-website:1.0
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


# Open http://localhost:8080. It looks good
mkdir sinatra
# Now modify index.html and refresh the website. It does not refresh
cd sinatra
# Let's stop and rm the container and rebuild using a volume
touch Dockerfile
docker rm -f my-site
sudo docker build -t="ouruser/sinatra:v2" .
docker run -d -v $(pwd):/usr/share/nginx/html \
sudo docker push ouruser/sinatra
  -p 8080:80 --name my-site my-website:1.0
sudo docker rmi training/sinatra
# Now any changes on index.html will refresh on the website
</syntaxhighlight>
</syntaxhighlight>


=== Define volumes in images ===
* 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)
A few samples of volume definition
<pre>
<pre>
VOLUME /app/data
$ sudo docker run -t -i training/sinatra /bin/bash
VOLUME /app/data, /app/profiles, /app/config
2014/12/31 02:43:26 exec format error
VOLUME {"/app/data", "/app/profiles", "/app/config"]
</pre>
</pre>
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.
=== 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 image pull mongo:3.7
docker load -i out.tar
docker image inspect --format='{{json .ContainerConfig.Volumes}}' \
# Or decompress the file
      mongo:3.7 | jq
docker load < out.tar.gz
# {
#  "/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
</syntaxhighlight>
</syntaxhighlight>


=== Differences between VOLUME and '-v|--volume' ===
=== Docker Image Manifest ===
https://stackoverflow.com/a/25312719
[https://www.cloudsavvyit.com/12330/what-is-a-docker-image-manifest/ What Is a Docker Image Manifest?]


=== Backup and restore container ===
=== Resources allocated to a container using docker? ===
* https://docs.docker.com/storage/volumes/#backup-restore-or-migrate-data-volumes
https://stackoverflow.com/questions/16084741/how-do-i-set-resources-allocated-to-a-container-using-docker
* [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]


=== Container Memory Limits, Setting Available CPUs, Allocating memory and CPU ===
== hub.docker.com ==
* [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]
* Note that Dockerfile is optional on https://registry.hub.docker.com.
* 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
: <syntaxhighlight lang='bash'>
: <syntaxhighlight lang='bash'>
docker run \
docker tag local-image:tagname new-repo:tagname
    -rm \ ## Automatically remove the container when it exits
docker login
    --memory=6g \ ## memory limit
docker push new-repo:tagname
    --cpus=1.5 \ ## number of CPUs
</syntaxhighlight>
    -v /shared/data-store:/home/rstudio/data \
* [https://stackoverflow.com/a/28349540 How to push a docker image to a private repository]
    -v /shared/library-store:/usr/local/lib/R/host-site-library \
* [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?
    -e PASSWORD=bioc \
* Search all repositories related to [https://registry.hub.docker.com/search?q=r&searchfield= R]
    -p 8787:8787 \
* [http://phusion.github.io/baseimage-docker/ baseimage-docker]. I can use ping command without special argument when I start phusion/baseimage.
        bioconductor/bioconductor_full:devel
: <syntaxhighlight lang='bash'>
docker pull phusion/baseimage
docker run -ti phusion/baseimage /bin/bash
</syntaxhighlight>
</syntaxhighlight>
* [https://docs.docker.com/docker-for-mac/ Get started with Docker Desktop for Mac], [https://docs.docker.com/docker-for-windows/ Windows]
* 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).
* [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]


== Work with container images ==
=== Set up a private Docker registry ===
* https://docs.docker.com/userguide/dockerimages/
* https://docs.docker.com/registry/ <syntaxhighlight lang='bash'>
 
docker run -d -p 5000:5000 --name registry registry:2
=== List images by size or name ===
docker pull ubuntu
<pre>
docker image tag ubuntu localhost:5000/myfirstimage
# by size
docker push localhost:5000/myfirstimage
docker images --format "{{.ID}}\t{{.Size}}\t{{.Repository}}" | sort -k 2 -h
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]


# by name
=== Github registry ===
docker images --format "{{.ID}}\t{{.Size}}\t{{.Repository}}" | sort -k 3
* [https://www.docker.com/blog/docker-support-for-the-new-github-container-registry/ Docker Support for the New GitHub Container Registry]
</pre>
* [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)]


=== List specific columns ===
=== Google cloud registry ===
<pre>
[https://seandavi.github.io/2019/02/using-google-cloud-registry-for-private-docker-images/ Using google cloud registry for private docker images]
docker images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}'
</pre>


=== Create an image interactively using '''commit''' - Example 1 ===
== Dockerfile ==
The example is from the book 'Learn Docker - Fundamentals of Docker 18.x'.
* [https://docs.docker.com/reference/builder/ Dockerfile Reference]
<syntaxhighlight lang='bash'>
* [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 container run -it --name sample alpine /bin/sh
* <strike><span style="color: red">Remember to put the Dockerfile in an empty directory</span></strike>.
# apk update && apk add iputils
* [https://medium.com/better-programming/what-goes-into-a-dockerfile-ff0ace591060 What goes into a Dockerfile]
# ping 127.0.0.1
* Keywords
# exit
** FROM. If we want to start from scratch, we can use ''FROM scratch''.
docker container ls -a | grep sample
** RUN. The argument for RUN is any valid Linux command.
docker container diff sample
** [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].
</syntaxhighlight>
** COPY & ADD.
We can now use the ''docker container commit'' command to persist our modifications and create a new image from them
*** "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?]
<syntaxhighlight lang='bash'>
*** "ADD sample.tar /app/bin" will unpack the ''sample.tar' file into the target folder
docker container commit sample my-alpine
*** "ADD <nowiki>http://example.com/sample.txt</nowiki> /data/" will copy the remote file sample.txt into the target file
docker images ls
** WORKDIR. Define the working directory or context that is used when a container is run from the image.
</syntaxhighlight>
** 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]


If we want to see how our custom image has been built, we can use the ''history'' command as follows:
=== Examples of Dockerfile ===
<syntaxhighlight lang='bash'>
* [https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers Only the instructions RUN, COPY, ADD create layers.]
docker image history my-alpine
* A sample. Six layers (lines). The first line is the Base Layer.
# IMAGE              CREATED              CREATED BY                                      SIZE    COMMENT
<pre>
# 0f105057899b        About a minute ago  /bin/sh                                        1.55MB             
FROM python:2.7
# 196d12cf6ab1        4 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]             0B                 
RUN mkdir -p /app
# <missing>           4 weeks ago          /bin/sh -c #(nop) ADD file:25c10b1d1b41d46a1…  4.41MB
WORKDIR /app
</syntaxhighlight>
COPY ./requirements.txt /app/
The first layer in the preceding list is the one we just created by adding the iputils package.
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>
* 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'''.


=== Create an image interactively using '''commit''' - Example 2 ===
The same technique does not work on alpine if I try to create a new file in the container.
* [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.  
<pre>
* [http://www.techrepublic.com/article/how-to-commit-changes-to-a-docker-image/ How to commit changes to a docker image]
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>


<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.
=== How to use Dockerfile ===
https://docs.docker.com/engine/reference/commandline/build/


[https://stackoverflow.com/a/55034787 The . simply means "current working directory"].
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
sudo docker search sinatra
docker build -f Dockerfile -t arraytools/myimagename .
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 build -t [myname] . 
cd sinatra
# Multiple tags
touch Dockerfile
docker build -t arraytools/biospear:latest -t arraytools/biospear:3.6.0 .
sudo docker build -t="ouruser/sinatra:v2" .
</syntaxhighlight>
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)
In the above example, we can create the image by
<pre>
$ sudo docker run -t -i training/sinatra /bin/bash
2014/12/31 02:43:26 exec format error
</pre>
 
=== 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'>
<syntaxhighlight lang='bash'>
docker save -o out.tar <image name>
docker image build -t pinger .
# Or better to compress the file
docker save <docker image name> | gzip > out.tar.gz
</syntaxhighlight>
</syntaxhighlight>
And restore
We can run a container from the pinger image
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker load -i out.tar
docker container run --rm -it pinger
# Or decompress the file
docker load < out.tar.gz
</syntaxhighlight>
</syntaxhighlight>


=== Docker Image Manifest ===
=== Docker Build Args ===
[https://www.cloudsavvyit.com/12330/what-is-a-docker-image-manifest/ What Is a Docker Image Manifest?]
[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]


=== Resources allocated to a container using docker? ===
=== Clean up after failed builds ===
https://stackoverflow.com/questions/16084741/how-do-i-set-resources-allocated-to-a-container-using-docker
[https://gist.github.com/kuznero/0c751283ea77177a1db9 Cleanup docker images and containers after failed builds]
<pre>
#!/bin/bash
docker rm $(docker ps -aq) \
  docker rmi $(docker images | grep "^<none>" | awk '{print $3}')
</pre>


== hub.docker.com ==
=== ENTRYPOINT and CMD ===
* Note that Dockerfile is optional on https://registry.hub.docker.com.
* If your container acts like a command-line program, you can use '''ENTRYPOINT'''. If you are unsure, you can use '''CMD'''.
* 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
* [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.
: <syntaxhighlight lang='bash'>
* https://docs.docker.com/engine/reference/builder/#cmd
docker tag local-image:tagname new-repo:tagname
** [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.
docker login
** 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 push new-repo:tagname
 
'''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.
<syntaxhighlight lang='bash'>
docker container run --rm -it pinger -w 5 127.0.0.1
# ping the loopback for 5 seconds
</syntaxhighlight>
</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?
If we want to overwrite what's defined in the ''ENTRYPOINT'' in the Dockerfile, we need to use the ''--entrypoint'' parameter.
* Search all repositories related to [https://registry.hub.docker.com/search?q=r&searchfield= R]
<syntaxhighlight lang='bash'>
* [http://phusion.github.io/baseimage-docker/ baseimage-docker]. I can use ping command without special argument when I start phusion/baseimage.
docker container run --rm -it --entrypoint /bin/sh pinger
: <syntaxhighlight lang='bash'>
# we'll be inside the container. Type exit to leave the container
docker pull phusion/baseimage
docker run -ti phusion/baseimage /bin/bash
</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 ===
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://docs.docker.com/registry/ <syntaxhighlight lang='bash'>
 
docker run -d -p 5000:5000 --name registry registry:2
=== Temporary failure resolving 'deb.debian.org' when running "docker build" ===
docker pull ubuntu
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]
docker image tag ubuntu localhost:5000/myfirstimage
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>


=== Github registry ===
=== Best practices for writing Dockerfiles ===
* [https://www.docker.com/blog/docker-support-for-the-new-github-container-registry/ Docker Support for the New GitHub Container Registry]
* https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
* [https://docs.github.com/en/packages/guides/migrating-to-github-container-registry-for-docker-images Migrating to GitHub Container Registry for Docker images]
* [https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices/ Intro Guide to Dockerfile Best Practices]
* [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)]


=== Google cloud registry ===
=== Use multi-stage builds ===
[https://seandavi.github.io/2019/02/using-google-cloud-registry-for-private-docker-images/ Using google cloud registry for private docker images]
* https://docs.docker.com/develop/develop-images/multistage-build/
* [https://www.cloudsavvyit.com/9260/what-are-multi-stage-docker-builds/ What Are Multi-Stage Docker Builds?]


== Dockerfile ==
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'''.
* [https://docs.docker.com/reference/builder/ Dockerfile Reference]
 
* [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.
[https://github.com/nigelpoulton/atsea-sample-shop-app An example] from the "Docker Deep Dive" book.
* <strike><span style="color: red">Remember to put the Dockerfile in an empty directory</span></strike>.
* [https://medium.com/better-programming/what-goes-into-a-dockerfile-ff0ace591060 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.
** [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]
* [https://github.com/rocker-org/rocker rocker (R and RStudio)]
* [https://github.com/Bioconductor/bioc_docker/tree/master/out Bioconductor]


=== Examples of Dockerfile ===
=== tag after image was built ===
* [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>
<pre>
FROM python:2.7
$ docker tag <imageID> <newName>/<repoName>:<tagName>
RUN mkdir -p /app
WORKDIR /app
COPY ./requirements.txt /app/
RUN pip install -r requirements.txt
CMD ["python", "main.py"]
</pre>
</pre>
* Another example
 
=== About storage drivers ===
https://docs.docker.com/storage/storagedriver/#sharing-promotes-smaller-images
 
=== Privileged versus Root user in Docker ===
* [https://www.cloudsavvyit.com/5211/privileged-vs-root-in-docker-whats-the-difference/ Privileged versus Root in Docker: What’s the Difference?]
* [https://itnext.io/docker-and-kubernetes-root-vs-privileged-9d2a37453dec Docker and Kubernetes — root vs. privileged]
 
=== .dockerignore ===
[https://devopsheaven.com/docker/dockerignore/2018/04/25/using-dockerignore.html Using .dockerignore files to build better Docker images]
 
=== Dockerfile in One Line ===
<pre>
<pre>
FROM alpine:latest
FROM ubuntu
ENTRYPOINT ["ping"]
CMD ["8.8.8.8", "-c", "3"]
</pre>
</pre>
* Another example from [https://github.com/rocker-org/rocker/blob/master/r-base/4.0.0/Dockerfile RStudio]
Using This simple Dockerfile and the docker command '''sudo docker build -t scooby_snacks .''' will result in
<pre>
<pre>
FROM debian:testing
$ sudo docker images
RUN useradd docker \
REPOSITORY          TAG                IMAGE ID            CREATED            VIRTUAL SIZE
&& mkdir /home/docker \
ubuntu              15.04              2427658c75a1        42 hours ago        117.5 MB
&& chown docker:docker /home/docker \
ubuntu              vivid              2427658c75a1        42 hours ago        117.5 MB
&& addgroup docker staff
ubuntu              vivid-20150218      2427658c75a1        42 hours ago        117.5 MB
</pre>
ubuntu              utopic-20150211    78949b1e1cfd        42 hours ago        194.4 MB
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'''.
ubuntu              utopic              78949b1e1cfd        42 hours ago        194.4 MB
 
ubuntu              14.10              78949b1e1cfd        42 hours ago        194.4 MB
The same technique does not work on alpine if I try to create a new file in the container.
ubuntu              14.04              2d24f826cb16        42 hours ago        188.3 MB
<pre>
ubuntu              14.04.2            2d24f826cb16        42 hours ago        188.3 MB
FROM alpine:latest
ubuntu              trusty              2d24f826cb16        42 hours ago        188.3 MB
# Create a group and user; not useful for creating files in host OS
ubuntu              trusty-20150218.1  2d24f826cb16        42 hours ago        188.3 MB
RUN addgroup -S appgroup && adduser -S appuser -G appgroup \
ubuntu              latest              2d24f826cb16        42 hours ago        188.3 MB
          && chown appuser:appgroup /home/appuser
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>
</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>


=== How to use Dockerfile ===
== List all tags of an image ==
https://docs.docker.com/engine/reference/commandline/build/
[https://stackoverflow.com/a/39454426 How can I list all tags for a Docker image on a remote registry?]


[https://stackoverflow.com/a/55034787 The . simply means "current working directory"].
=== Tag the image with the git commit ID ===
<syntaxhighlight lang='bash'>
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 .
</syntaxhighlight>
 
In the above example, we can create the image by
<syntaxhighlight lang='bash'>
docker image build -t pinger .
</syntaxhighlight>
We can run a container from the pinger image
<syntaxhighlight lang='bash'>
docker container run --rm -it pinger
</syntaxhighlight>
 
=== Clean up after failed builds ===
[https://gist.github.com/kuznero/0c751283ea77177a1db9 Cleanup docker images and containers after failed builds]
<pre>
<pre>
#!/bin/bash
$ docker build -t REPOS/IMAGE:$(git rev-parse --verify HEAD)
docker rm $(docker ps -aq) \
  docker rmi $(docker images | grep "^<none>" | awk '{print $3}')
</pre>
</pre>


=== ENTRYPOINT and CMD ===
== Run a shell script on host ==
* If your container acts like a command-line program, you can use '''ENTRYPOINT'''. If you are unsure, you can use '''CMD'''.
* https://docs.docker.com/engine/reference/commandline/run/
* [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.
* [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]
* https://docs.docker.com/engine/reference/builder/#cmd
<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+ */ " >
** [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.
$ docker run -v /path/to/sample_script.sh:/sample_script.sh \
** 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.
  --rm ubuntu bash sample_script.sh


'''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.
# GATK container example
<syntaxhighlight lang='bash'>
# First we log in interactive and see where is the default location (/usr in this case)
docker container run --rm -it pinger -w 5 127.0.0.1
$ docker run --rm -i -t broadinstitute/gatk3:3.8-0 bash
# ping the loopback for 5 seconds
$ cat > tmp.sh << EOF
</syntaxhighlight>
> 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
</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>
docker run -d -v$(pwd):/my SOMEIMAGE bash
docker exec -d Test bash /my/script.sh
</pre>
* Create a Dockerfile https://forums.docker.com/t/how-to-run-bash-command-after-startup/21631/2


If we want to overwrite what's defined in the ''ENTRYPOINT'' in the Dockerfile, we need to use the ''--entrypoint'' parameter.
== Link containers together ==
<syntaxhighlight lang='bash'>
* https://docs.docker.com/userguide/dockerlinks/
docker container run --rm -it --entrypoint /bin/sh pinger
* [https://hub.docker.com/r/simplyintricate/mediawiki/ Mediawiki example]
# we'll be inside the container. Type exit to leave the container
</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.
== Manage data in containers ==
* https://docs.docker.com/storage/volumes/
* https://codereviewvideos.com/course/docker-tutorial-for-beginners/video/part-2-docker-volumes-volumes


=== Temporary failure resolving 'deb.debian.org' when running "docker build" ===
== Assign a static IP to a container ==
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]
* [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]
* https://stackoverflow.com/questions/27937185/assign-static-ip-to-docker-container <syntaxhighlight lang='bash'>
# Step 1. create you own docker network (mynet123)
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>
* 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)


=== Best practices for writing Dockerfiles ===
== Running Multiple Docker Services on the Same Server ==
* https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
[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]
* [https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices/ Intro Guide to Dockerfile Best Practices]


=== Use multi-stage builds ===
== Firewall ==
* https://docs.docker.com/develop/develop-images/multistage-build/
[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/9260/what-are-multi-stage-docker-builds/ What Are Multi-Stage Docker 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'''.
== Docker DNS/internet problem ==
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://github.com/nigelpoulton/atsea-sample-shop-app An example] from the "Docker Deep Dive" book.
[https://development.robinwinslow.uk/2016/06/23/fix-docker-networking-dns/ Fix Docker's networking DNS config]


=== tag after image was built ===
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.
 
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]]).
<pre>
<pre>
$ docker tag <imageID> <newName>/<repoName>:<tagName>
{
    "dns": ["XXX.XX.XX.XX", "YYY.YY.YY.YY"]
}
</pre>
</pre>
Then restart the docker service: '''sudo service docker restart'''


=== About storage drivers ===
A quick test on the DNS problem is
https://docs.docker.com/storage/storagedriver/#sharing-promotes-smaller-images
<syntaxhighlight lang='bash'>
docker run --rm busybox nslookup google.com
</syntaxhighlight>


=== Privileged versus Root user in Docker ===
== Working with Docker hub ==
* [https://www.cloudsavvyit.com/5211/privileged-vs-root-in-docker-whats-the-difference/ Privileged versus Root in Docker: What’s the Difference?]
https://docs.docker.com/userguide/dockerrepos/
* [https://itnext.io/docker-and-kubernetes-root-vs-privileged-9d2a37453dec Docker and Kubernetes — root vs. privileged]


=== .dockerignore ===
=== Github Actions ===
[https://devopsheaven.com/docker/dockerignore/2018/04/25/using-dockerignore.html Using .dockerignore files to build better Docker images]
* [https://docs.github.com/en/actions/language-and-framework-guides/github-actions-for-docker GitHub Actions for Docker]
* [https://docs.github.com/en/actions/language-and-framework-guides/publishing-docker-images Publishing Docker images]
* See my [[Github#Github_Actions_.28GHA.29|Github]] page.


=== Dockerfile in One Line ===
== Enabling HTTPS/Let's encrypt ==
<pre>
* [https://caddyserver.com/ Caddy]
FROM ubuntu
* https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion
</pre>
* [https://medium.com/bros/enabling-https-with-lets-encrypt-over-docker-9cad06bdb82b Enabling HTTPS with Let's Encrypt on Docker]
Using This simple Dockerfile and the docker command '''sudo docker build -t scooby_snacks .''' will result in
* [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].
<pre>
* [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'>
$ sudo docker images
ERROR: for nginx  Cannot start service nginx: b'driver failed programming external connectivity on endpoint
REPOSITORY          TAG                IMAGE ID            CREATED            VIRTUAL SIZE
nginx (879b01885acd6a0778d9403f4220851e83bd2ff8de643ce91c21cecd25419f83): Error starting userland proxy:
ubuntu              15.04              2427658c75a1        42 hours ago        117.5 MB
listen tcp 0.0.0.0:443: bind: address already in use'
ubuntu              vivid              2427658c75a1        42 hours ago        117.5 MB
ERROR: Encountered errors while bringing up the project.
ubuntu              vivid-20150218      2427658c75a1        42 hours ago        117.5 MB
</syntaxhighlight>
ubuntu              utopic-20150211    78949b1e1cfd        42 hours ago        194.4 MB
* [https://medium.com/bros/enabling-https-with-lets-encrypt-over-docker-9cad06bdb82b Enabling HTTPS with Let's Encrypt on Docker] using Nginx.
ubuntu              utopic              78949b1e1cfd        42 hours ago        194.4 MB
 
ubuntu              14.10              78949b1e1cfd        42 hours ago        194.4 MB
== Enabling HTTPS by self-sign certificates ==
ubuntu              14.04              2d24f826cb16        42 hours ago        188.3 MB
* [https://www.johnmackenzie.co.uk/post/creating-self-signed-ssl-certificates-for-docker-and-nginx/ Creating Self-Signed SSL Certificates For Docker and Nginx]
ubuntu              14.04.2            2d24f826cb16        42 hours ago        188.3 MB
* [https://medium.com/@oliver.zampieri/self-signed-ssl-reverse-proxy-with-docker-dbfc78c05b41 Self-signed SSL Reverse proxy with Docker]
ubuntu              trusty              2d24f826cb16        42 hours ago        188.3 MB
* [https://codefresh.io/docker-tutorial/using-docker-generate-ssl-certificates/ Using Docker to Generate SSL Certificates]
ubuntu              trusty-20150218.1  2d24f826cb16        42 hours ago        188.3 MB
* [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]
ubuntu              latest              2d24f826cb16        42 hours ago        188.3 MB
* [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]
scooby_snacks      latest              2d24f826cb16        42 hours ago        188.3 MB
 
ubuntu              precise            1f80e9ca2ac3        42 hours ago        131.5 MB
== traefik: The Cloud Native Application Proxy ==
ubuntu             precise-20150212    1f80e9ca2ac3        42 hours ago        131.5 MB
* https://traefik.io/traefik/
ubuntu              12.04.5            1f80e9ca2ac3        42 hours ago        131.5 MB
* [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]
ubuntu              12.04              1f80e9ca2ac3        42 hours ago        131.5 MB
* [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]
ubuntu             14.04.1            5ba9dab47459        3 weeks ago        188.3 MB
* [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]
ubuntu              12.10              c5881f11ded9        8 months ago        172.2 MB
* [https://medium.com/accesto/docker-reverse-proxy-using-traefik-2657c0086a3d Docker reverse proxy using Traefik]
ubuntu              quantal            c5881f11ded9        8 months ago        172.2 MB
* [https://blog.eleven-labs.com/en/using-traefik-as-a-reverse-proxy/ USING TRAEFIK AS A REVERSE PROXY]
ubuntu              13.04              463ff6be4238        8 months ago        169.4 MB
* [https://youtu.be/N5EmluXSbEg How to Install Traefik 2 on OMV and Docker] DB Tech 2020. Cloudflare, Portainer. Airsonic.
ubuntu              raring              463ff6be4238        8 months ago        169.4 MB
* [https://youtu.be/liV3c9m_OX8 Put Wildcard Certificates and SSL on EVERYTHING - Traefik Tutorial] Apr 2021
ubuntu              13.10              195eb90b5349        8 months ago        184.7 MB
* Raspberry Pi
ubuntu              saucy              195eb90b5349        8 months ago        184.7 MB
** [https://www.alexhyett.com/traefik-vs-nginx-docker-raspberry-pi Traefik vs Nginx for Reverse Proxy with Docker on a Raspberry Pi]
ubuntu              10.04              3db9c44f4520        10 months ago      183 MB
** [https://codecaptured.com/blog/self-hosting-pi-hole-with-docker-and-traefik/ Self-Hosting Pi-hole with Docker and Traefik]
ubuntu              lucid              3db9c44f4520        10 months ago      183 MB
** [https://blog.pankajgarg.com/helloaspnetcoreonpi/ Running ASP.NET core web application on Raspberry Pi]
</pre>
* [https://youtu.be/liV3c9m_OX8 Put Wildcard Certificates and SSL on EVERYTHING - Traefik Tutorial] (video)


== List all tags of an image ==
== Nginx proxy manager ==
[https://stackoverflow.com/a/39454426 How can I list all tags for a Docker image on a remote registry?]
* https://nginxproxymanager.com/
 
* [https://www.the-digital-life.com/nginx-proxy-manager/ NGINX Proxy Manager – How-To Installation and Configuration]
=== Tag the image with the git commit ID ===
* [https://youtu.be/CSbgLBcIuwE Access your internal websites! Nginx Reverse Proxy in Home Assistant]
<pre>
* [https://www.howtoforge.com/how-to-install-and-use-nginx-proxy-manager/ How to Install and Use Nginx Proxy Manager with Docker] 2022
$ docker build -t REPOS/IMAGE:$(git rev-parse --verify HEAD)
* [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>
</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]


== Run a shell script on host ==
== Running multiple web applications on a Docker host ==
* https://docs.docker.com/engine/reference/commandline/run/
* 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://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]
* https://medium.com/@francoisromain/host-multiple-websites-with-https-inside-docker-containers-on-a-single-server-18467484ab95. Nginx reverse-proxy is used.
<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+ */ " >
* 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'>
$ docker run -v /path/to/sample_script.sh:/sample_script.sh \
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy
  --rm ubuntu bash sample_script.sh
 
sudo nano /etc/hosts # add blog.domain.com and jenkins.domain.com for our testing purpose


# GATK container example
docker run -d --expose 80 -e VIRTUAL_HOST=blog.domain.com wordpress
# First we log in interactive and see where is the default location (/usr in this case)
docker run -d --name jenkinsci --expose 8080 -e VIRTUAL_HOST=jenkins.domain.com -e VIRTUAL_PORT=8080 jenkins
$ docker run --rm -i -t broadinstitute/gatk3:3.8-0 bash
</syntaxhighlight>
$ cat > tmp.sh << EOF
** Use VIRTUAL_PORT if there are multiple ports associated with a container
> pwd
** Use VIRTUAL_HOST if there are multiple domains associated with a container
> ls
** SSL and et al
> 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>
docker run -d -v$(pwd):/my SOMEIMAGE bash
docker exec -d Test bash /my/script.sh
</pre>
* Create a Dockerfile https://forums.docker.com/t/how-to-run-bash-command-after-startup/21631/2


== Link containers together ==
== Authentication: Authelia ==
* https://docs.docker.com/userguide/dockerlinks/
[https://www.youtube.com/watch?v=4UKOh3ssQSU Additional Self-Hosted Security with Authelia on NGINX Proxy Manager] (video)
* [https://hub.docker.com/r/simplyintricate/mediawiki/ Mediawiki example]


== Manage data in containers ==
== GUI apps ==
* https://docs.docker.com/storage/volumes/
* [https://www.cloudsavvyit.com/10520/how-to-run-gui-applications-in-a-docker-container/ How to Run GUI Applications in a Docker Container]
* https://codereviewvideos.com/course/docker-tutorial-for-beginners/video/part-2-docker-volumes-volumes
* https://github.com/mviereck/x11docker/ which was used by [https://github.com/ehough/docker-kodi Docker-kodi]
 
* https://pelle.io/2014/07/11/delivering-gui-applications-with-docker/ Forward X11 approach
== Assign a static IP to a container ==
* https://linuxmeerkat.wordpress.com/2014/10/17/running-a-gui-application-in-a-docker-container/ Forward X11
* [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]
* http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ Share X11 socket
* https://stackoverflow.com/questions/27937185/assign-static-ip-to-docker-container <syntaxhighlight lang='bash'>
* https://github.com/rogaha/docker-desktop  Xpra + Xephyr
# Step 1. create you own docker network (mynet123)
* https://github.com/fcwu/docker-ubuntu-vnc-desktop VNC approach
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>
* 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)


== Firewall ==
=== Docker-OSX ===
[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://github.com/sickcodes/Docker-OSX


== Docker DNS/internet problem ==
== Pruning unused resources ==
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).
* 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


[https://development.robinwinslow.uk/2016/06/23/fix-docker-networking-dns/ Fix Docker's networking DNS config]
docker container prune -f
 
docker container rm -f $(docker container ls -aq) # remove even the running containers
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.
</syntaxhighlight>
* Prune images
<syntaxhighlight lang='bash'>
docker images prune # unused image layers
</syntaxhighlight>
* Prune volumes
<syntaxhighlight lang='bash'>
docker volume prune # unused volumes by at least one container


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]]).
docker volume prune --filter 'label=demo'
<pre>
docker volume prune --filter 'label=demo' --filter 'label=test'
{
</syntaxhighlight>
    "dns": ["XXX.XX.XX.XX", "YYY.YY.YY.YY"]
* Prune networks
}
<syntaxhighlight lang='bash'>
</pre>
docker network prune
Then restart the docker service: '''sudo service docker restart'''
</syntaxhighlight>
 
* Prune everything
A quick test on the DNS problem is
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker run --rm busybox nslookup google.com
docker system prune
</syntaxhighlight>
</syntaxhighlight>


== Working with Docker hub ==
== Plugins ==
https://docs.docker.com/userguide/dockerrepos/
[https://www.cloudsavvyit.com/15066/how-to-manage-docker-engine-plugins/ How to Manage Docker Engine Plugins]


=== Github Actions ===
== Misc ==
* [https://docs.github.com/en/actions/language-and-framework-guides/github-actions-for-docker GitHub Actions for Docker]
=== LXC (raw Linux containers) ===
* [https://docs.github.com/en/actions/language-and-framework-guides/publishing-docker-images Publishing Docker images]
* https://help.ubuntu.com/lts/serverguide/lxc.html
* See my [[Github#Github_Actions_.28GHA.29|Github]] page.
* https://help.ubuntu.com/community/LXC
* https://askubuntu.com/questions/293275/what-is-lxc-and-how-to-get-started
* [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]
* [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]
* [https://blog.simos.info/trying-out-lxd-containers-on-our-ubuntu/ Trying out LXD containers on our Ubuntu]


== Enabling HTTPS/Let's encrypt ==
==== LXC vs Docker ====
* [https://caddyserver.com/ Caddy]
* https://diveintodocker.com/blog/why-i-got-started-with-docker
* https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion
* https://unix.stackexchange.com/questions/254956/what-is-the-difference-between-docker-lxd-and-lxc and https://i.stack.imgur.com/a5Neb.png
* [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].
* [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'>
ERROR: for nginx  Cannot start service nginx: b'driver failed programming external connectivity on endpoint
nginx (879b01885acd6a0778d9403f4220851e83bd2ff8de643ce91c21cecd25419f83): Error starting userland proxy:
listen tcp 0.0.0.0:443: bind: address already in use'
ERROR: Encountered errors while bringing up the project.
</syntaxhighlight>
* [https://medium.com/bros/enabling-https-with-lets-encrypt-over-docker-9cad06bdb82b Enabling HTTPS with Let's Encrypt on Docker] using Nginx.


== Enabling HTTPS by self-sign certificates ==
=== Vagrant vs Docker ===
* [https://www.johnmackenzie.co.uk/post/creating-self-signed-ssl-certificates-for-docker-and-nginx/ Creating Self-Signed SSL Certificates For Docker and Nginx]
* http://stackoverflow.com/questions/16647069/should-i-use-vagrant-or-docker-io-for-creating-an-isolated-environment
* [https://medium.com/@oliver.zampieri/self-signed-ssl-reverse-proxy-with-docker-dbfc78c05b41 Self-signed SSL Reverse proxy with Docker]
* https://deliciousbrains.com/vagrant-docker-wordpress-development/
* [https://codefresh.io/docker-tutorial/using-docker-generate-ssl-certificates/ Using Docker to Generate SSL Certificates]
** 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://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’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://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]
* https://youtu.be/9QGkJvbLpRA?t=3m22s
** 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


== traefik: The Cloud Native Application Proxy ==
=== Date/Time zone ===
* https://traefik.io/traefik/
* List of time zone. [https://docs.diladele.com/docker/timezones.html Setting Local Time in Docker]; e.g. "America/New_York" or "US/Eastern".
* [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://stackoverflow.com/questions/22800624/will-docker-container-auto-sync-time-with-the-host-machine
* [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]
<syntaxhighlight lang='bash'>
* [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]
docker run --rm -t -i -v /etc/localtime:/etc/localtime:ro ubuntu date
* [https://medium.com/accesto/docker-reverse-proxy-using-traefik-2657c0086a3d Docker reverse proxy using Traefik]
</syntaxhighlight>
* [https://blog.eleven-labs.com/en/using-traefik-as-a-reverse-proxy/ USING TRAEFIK AS A REVERSE PROXY]
* https://serverfault.com/questions/683605/docker-container-time-timezone-will-not-reflect-changes
* [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)


== Nginx proxy manager ==
=== Access the internet from the container ===
* https://nginxproxymanager.com/
Run the container with the '--net=host' option
* [https://www.the-digital-life.com/nginx-proxy-manager/ NGINX Proxy Manager – How-To Installation and Configuration]
<syntaxhighlight lang='bash'>
* [https://youtu.be/CSbgLBcIuwE Access your internal websites! Nginx Reverse Proxy in Home Assistant]
sudo docker run --net=host -it ubuntu /bin/bash
* [https://www.howtoforge.com/how-to-install-and-use-nginx-proxy-manager/ How to Install and Use Nginx Proxy Manager with Docker] 2022
</syntaxhighlight>
* [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]


== Running multiple web applications on a Docker host ==
=== How to transfer/copy an image to another host ===
* 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://stackoverflow.com/a/23938978 How to copy Docker images from one host to another without using a repository]
* https://medium.com/@francoisromain/host-multiple-websites-with-https-inside-docker-containers-on-a-single-server-18467484ab95. Nginx reverse-proxy is used.
<syntaxhighlight lang='bash'>
* 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'>
# Step 1: save the Docker image as a tar file:
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy
docker save -o <path for generated tar file> <image name>


sudo nano /etc/hosts # add blog.domain.com and jenkins.domain.com for our testing purpose
# Step 2: copy your image to a new system with regular file transfer tools such as cp or scp.  


docker run -d --expose 80 -e VIRTUAL_HOST=blog.domain.com wordpress
# Step 3: After that you will have to load the image into Docker:
docker run -d --name jenkinsci --expose 8080 -e VIRTUAL_HOST=jenkins.domain.com -e VIRTUAL_PORT=8080 jenkins
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).
 
Or https://stackoverflow.com/a/39716019
<syntaxhighlight lang='bash'>
# Step 1:
docker save docker-image-name | gzip > my-image.tar.gz
# Step 3:
docker load < my-image.tar.gz
</syntaxhighlight>
</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


== GUI apps ==
=== Where are Docker images stored on the host: /var/lib/docker ===
* [https://www.cloudsavvyit.com/10520/how-to-run-gui-applications-in-a-docker-container/ How to Run GUI Applications in a Docker Container]
* http://blog.thoward37.me/articles/where-are-docker-images-stored/
* https://github.com/mviereck/x11docker/ which was used by [https://github.com/ehough/docker-kodi Docker-kodi]
* http://stackoverflow.com/questions/19234831/where-are-docker-images-stored-on-the-host-machine
* https://pelle.io/2014/07/11/delivering-gui-applications-with-docker/ Forward X11 approach
* https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-storage-driver
* https://linuxmeerkat.wordpress.com/2014/10/17/running-a-gui-application-in-a-docker-container/ Forward X11
* http://stackoverflow.com/questions/21016210/function-of-docker-directory-structure-in-var-lib-docker
* http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ Share X11 socket
* [https://foxutech.com/manage-docker-images-local-disk/ How to Manage Docker images on local disk]
* https://github.com/rogaha/docker-desktop  Xpra + Xephyr
* https://github.com/fcwu/docker-ubuntu-vnc-desktop VNC approach


=== Docker-OSX ===
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/sickcodes/Docker-OSX


== Pruning unused resources ==
'''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.
* Prune containers
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker container prune # remove all containers that are not in ''running'' status
sudo service docker stop  # or sudo systemctl stop docker
                      # Docker will ask for confirmation before deleting the containers
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>


docker container prune -f
'''2. Change the default location to another place'''. For example,
docker container rm -f $(docker container ls -aq) # remove even the running containers
</syntaxhighlight>
* Prune images
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker images prune # unused image layers
sudo nano /etc/default/docker
# Add a line DOCKER_OPTS="-g /home/brb/Docker"
</syntaxhighlight>
</syntaxhighlight>
* Prune volumes
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'>
<syntaxhighlight lang='bash'>
docker volume prune # unused volumes by at least one container
$ docker run --rm -ti rocker/r-base
$ docker images
$ docker -v
Docker version 1.0.1, build 990021a


docker volume prune --filter 'label=demo'
$ docker -D info | grep Root
docker volume prune --filter 'label=demo' --filter 'label=test'
Root Dir: /home/brb/Docker/aufs
</syntaxhighlight>
</syntaxhighlight>
* Prune networks
 
=== Consuming Docker system events ===
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
docker network prune
# Open a new terminal
</syntaxhighlight>
docker system events
* Prune everything
# This command is a blocking command.
<syntaxhighlight lang='bash'>
# Thus, when you execute it in your terminal session the according session is blocked.
docker system prune
 
# Open another terminal
docker container run --rm alpine echo "Hello World"
</syntaxhighlight>
</syntaxhighlight>


== Plugins ==
=== Monitor tools ===
[https://www.cloudsavvyit.com/15066/how-to-manage-docker-engine-plugins/ How to Manage Docker Engine Plugins]
* [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]
 
== [https://docs.docker.com/machine/overview/ 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 [https://sreeninet.wordpress.com/2015/05/31/docker-machine/ here].
* Provision and manage multiple remote Docker hosts
* Provision Swarm clusters


== Misc ==
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.
=== LXC (raw Linux containers) ===
* https://help.ubuntu.com/lts/serverguide/lxc.html
* https://help.ubuntu.com/community/LXC
* https://askubuntu.com/questions/293275/what-is-lxc-and-how-to-get-started
* [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]
* [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]
* [https://blog.simos.info/trying-out-lxd-containers-on-our-ubuntu/ Trying out LXD containers on our Ubuntu]


==== LXC vs Docker ====
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://diveintodocker.com/blog/why-i-got-started-with-docker
* https://unix.stackexchange.com/questions/254956/what-is-the-difference-between-docker-lxd-and-lxc and https://i.stack.imgur.com/a5Neb.png


=== Vagrant vs 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.
* http://stackoverflow.com/questions/16647069/should-i-use-vagrant-or-docker-io-for-creating-an-isolated-environment
<pre>
* https://deliciousbrains.com/vagrant-docker-wordpress-development/
$ docker-machine help
** 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).
$ docker-machine create --driver=virtualbox test
** 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.
# Follow its hint on the output, issue the following command
* https://youtu.be/9QGkJvbLpRA?t=3m22s
$ docker-machine env test
** Docker uses container technology while vagrant uses virtual machines.
# Follow its hint on the output, issue the following command
** If security is a concern, use vagrant and virtual machine
$ eval$(docker-machine env test) # will configure the docker CLI to connect to this docker machine 'test'
** For speeding development and sharing, use Docker.
                                # This is equivalent to running 4 export commands on the command line
** Most teams use both to run a smooth operation
$ docker-machine ls  # Very useful
$ docker-machine stop test
$ docker-machine ip test
$ docker-machine start test
$ docker-machine rm test
</pre>


=== Date/Time zone ===
[https://youtu.be/rnaLmSkZfKk Play Docker Machine on Mac with Virtualbox]. Docker can be used to create a virtual machine just like Vagrant.
* http://tedwise.com/2015/05/02/setting-the-timezone-in-a-docker-image/
<pre>
* https://stackoverflow.com/questions/22800624/will-docker-container-auto-sync-time-with-the-host-machine
$ docker-machine create -d virtualbox demo
<syntaxhighlight lang='bash'>
$ docker-machine ls
docker run --rm -t -i -v /etc/localtime:/etc/localtime:ro ubuntu date
</syntaxhighlight>
* https://serverfault.com/questions/683605/docker-container-time-timezone-will-not-reflect-changes


=== Access the internet from the container ===
# first way to access a Docker host
Run the container with the '--net=host' option
$ docker-machine ssh demo
<syntaxhighlight lang='bash'>
docker@demo:~$ docker images # empty for now
sudo docker run --net=host -it ubuntu /bin/bash
</syntaxhighlight>


=== How to transfer/copy an image to another host ===
# second way to access
[https://stackoverflow.com/a/23938978 How to copy Docker images from one host to another without using a repository]
$ docker-machine env demo
<syntaxhighlight lang='bash'>
$ eval $(docker-machine env demo)
# Step 1: save the Docker image as a tar file:
$ docker version
docker save -o <path for generated tar file> <image name>
</pre>


# Step 2: copy your image to a new system with regular file transfer tools such as cp or scp.
[http://rancher.com/rancher-os/ RancherOS demo video] used the '''docker-machine''' command to pull and run the RancherOS.
<pre>
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


# Step 3: After that you will have to load the image into Docker:
sudo ros help
docker load -i <path to image tar file>
sudo ros console list
</syntaxhighlight>
sudo ros console switch ubunu
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).
apt-get help
</pre>


Or https://stackoverflow.com/a/39716019
== Docker Compose <docker-compose.yaml> ==
<syntaxhighlight lang='bash'>
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).
# Step 1:
 
docker save docker-image-name | gzip > my-image.tar.gz
* https://docs.docker.com/compose/ (the example will give an error when "RUN pip install -r requirements.txt")
# Step 3:
*# app.py
docker load < my-image.tar.gz
*# requirements.txt
</syntaxhighlight>
*# 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]


=== Where are Docker images stored on the host: /var/lib/docker ===
=== Download binary ===
* http://blog.thoward37.me/articles/where-are-docker-images-stored/
* https://github.com/docker/compose/releases
* http://stackoverflow.com/questions/19234831/where-are-docker-images-stored-on-the-host-machine
* [https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04 How To Install and Use Docker Compose on Ubuntu 20.04]
* https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-storage-driver
{{Pre}}
* http://stackoverflow.com/questions/21016210/function-of-docker-directory-structure-in-var-lib-docker
wget https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-linux-x86_64
* [https://foxutech.com/manage-docker-images-local-disk/ How to Manage Docker images on local disk]
sudo mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
</pre>


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.
=== Composerize ===
[https://ostechnix.com/convert-docker-run-commands-into-docker-compose-files/ Convert Docker Run Commands Into Docker-Compose Files]


'''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.
=== An example from 'Fundamentals of Docker' ===
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
sudo service docker stop  # or sudo systemctl stop docker
git clone https://github.com/fundamentalsofdocker/labs.git
sudo mv /var/lib/docker /a/new/location
cd labs/ch08
sudo ln -s /a/new/location /var/lib/docker # Create a symbolic link
docker-compose up
sudo service docker start  # or sudo systemctl start docker
# Open http://localhost:3000/pet
</syntaxhighlight>
</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.


'''2. Change the default location to another place'''. For example,
We can also run the application in the background
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
sudo nano /etc/default/docker
docker-compose up -d
# Add a line DOCKER_OPTS="-g /home/brb/Docker"
</syntaxhighlight>
</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:
 
To stop and clean up the application,
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
$ docker run --rm -ti rocker/r-base
docker-compose down
$ docker images
$ docker -v
Docker version 1.0.1, build 990021a
 
$ docker -D info | grep Root
Root Dir: /home/brb/Docker/aufs
</syntaxhighlight>
</syntaxhighlight>


=== Consuming Docker system events ===
If we also want to remove the volume for the database
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
# Open a new terminal
docker volume rm ch08_pets-data
docker system events
</syntaxhighlight>
# This command is a blocking command.
# Thus, when you execute it in your terminal session the according session is blocked.


# Open another terminal
=== An example from "How to Setup NGINX as Reverse Proxy Using Docker" ===
docker container run --rm alpine echo "Hello World"
See [[#Nginx_reverse_proxy|here]]. Only nginx is used.
</syntaxhighlight>


=== Monitor tools ===
=== An example from "Docker Deep Dive" (flask + redis) ===
* [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]
'''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.


== [https://docs.docker.com/machine/overview/ Docker Machine] ==
Another one [https://takacsmark.com/docker-compose-tutorial-beginners-by-example-basics/ Docker compose tutorial for beginners by example]
Docker Machine is a tool that lets you
<syntaxhighlight lang='bash'>
* 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].
$ git clone https://github.com/nigelpoulton/counter-app.git
* Provision and manage multiple remote Docker hosts
$ cd counter-app
* Provision Swarm clusters
$ ls
app.py  docker-compose.yml  Dockerfile  README.md  requirements.txt


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.
$ cat requirements.txt
flask


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.
$ cat Dockerfile
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]


[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.
$ cat docker-compose.yml
<pre>
version: "3.5"
$ docker-machine help
services:
$ docker-machine create --driver=virtualbox test
  web-fe:
# Follow its hint on the output, issue the following command
    build: .
$ docker-machine env test
    command: python app.py
# Follow its hint on the output, issue the following command
    ports:
$ eval$(docker-machine env test) # will configure the docker CLI to connect to this docker machine 'test'
      - target: 5000
                                # This is equivalent to running 4 export commands on the command line
        published: 5000
$ docker-machine ls  # Very useful
    networks:
$ docker-machine stop test
      - counter-net
$ docker-machine ip test
    volumes:
$ docker-machine start test
      - type: volume
$ docker-machine rm test
        source: counter-vol
</pre>
        target: /code
  redis:
    image: "redis:alpine"
    networks:
      counter-net:
 
networks:
  counter-net:


[https://youtu.be/rnaLmSkZfKk Play Docker Machine on Mac with Virtualbox]. Docker can be used to create a virtual machine just like Vagrant.
volumes:
<pre>
  counter-vol:
$ docker-machine create -d virtualbox demo
$ docker-machine ls


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


# second way to access
$ docker container ls
$ docker-machine env demo
$ eval $(docker-machine env demo)
$ docker version
</pre>


[http://rancher.com/rancher-os/ RancherOS demo video] used the '''docker-machine''' command to pull and run the RancherOS.
$ docker network ls
<pre>
NETWORK ID          NAME                    DRIVER              SCOPE
docker-machine create -d virtualbox --virtualbox-boot2docker-url https://releases.rancher.com/os/latest/rancheros.iso demo
2acef6dabde6        bridge                  bridge              local
docker-machine ssh demo
a2d42bc482ff        counterapp_counter-net  bridge              local
ps
e1e093b64282        host                    host                local
docker ps
7ecd0a6a9ebd        none                    null                local
sudo system-docker ps


sudo ros help
# Open the browser http://localhost:5000
sudo ros console list
$ docker-compose ps
sudo ros console switch ubunu
      Name                      Command              State          Ports       
apt-get help
-------------------------------------------------------------------------------------
</pre>
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 <docker-compose.yaml> ==
$ docker-compose stop
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-compose ps
# We can see stopping a Compose app does not delete the application


* https://docs.docker.com/compose/ (the example will give an error when "RUN pip install -r requirements.txt")
$ docker container ls -a
*# app.py
$ docker-compose rm    # delete a stopped Compose app
*# requirements.txt
                        # images, volumes and source code remain
*# Dockerfile
$ docker-compose restart
*# docker-compose.yml
                        # If you made changes to your Compose app since stopping,
* Some top-level '''keys''': version, services, networks, volumes
                        # these changes will not appear in the restarted app.
* [https://stackoverflow.com/questions/38507446/docker-dockerfile-vs-docker-compose-yml Dockerfile vs docker-compose.yml]
                        # You need to re-deploy the app to get the changes.
* A simple example of running [https://www.tutorialspoint.com/docker/docker_compose.htm nginx & mysqsl]
$ docker-compose ps
* [https://youtu.be/Qw9zlE3t8Ko Docker Compose in 12 Minutes]
$ docker-compose down  # stop and delete the app
* https://deliciousbrains.com/vagrant-docker-wordpress-development/
                        # images, volumes and source code remain
* https://github.com/kristophjunge/docker-mediawiki
$ docker-compose down --volumes # remove the data volume used by the Redis container
* [https://www.howtoforge.com/tutorial/docker-guide-dockerizing-python-django-application/ Docker Guide: Dockerizing Python Django Application] (cannot follow)
$ docker-compose up -d
* Examples:
$ docker volume ls
** [https://github.com/haroldtreen/epub-press EpubPress] local server
$ docker-compose  
** 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' ===
# We can make changes to files in the volume, from the host side,
<syntaxhighlight lang='bash'>
# and have them reflected immediately in the app.
git clone https://github.com/fundamentalsofdocker/labs.git
$ nano app.py  # do some changes
cd labs/ch08
$ docker volume inspect counterapp_counter-vol | grep Mount
docker-compose up
$ sudo cp app.py \
# Open http://localhost:3000/pet
  /var/lib/docker/volumes/counterapp_counter-vol/_data/app.py
</syntaxhighlight>
# Our changes should be reflected
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 --help
<syntaxhighlight lang='bash'>
docker-compose up -d
</syntaxhighlight>
</syntaxhighlight>


To stop and clean up the application,
<syntaxhighlight lang='bash'>
docker-compose down
</syntaxhighlight>


If we also want to remove the volume for the database
=== Docker-Compose persistent data MySQL ===
<syntaxhighlight lang='bash'>
https://stackoverflow.com/questions/39175194/docker-compose-persistent-data-mysql
docker volume rm ch08_pets-data
</syntaxhighlight>


=== An example from "How to Setup NGINX as Reverse Proxy Using Docker" ===
=== Connect to Docker daemon over ssh using docker-compose ===
See [[#Nginx_reverse_proxy|here]]. Only nginx is used.
[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]
 
=== Dockerfile + docker-compose ===
[https://stackoverflow.com/a/29487120 Docker Compose vs. Dockerfile - which is better?]


=== An example from "Docker Deep Dive" (flask + redis) ===
The Compose file describes the container in its running state, leaving the details on how to build the container to Dockerfiles.
'''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]
=== How to deploy on remote Docker hosts with docker-compose ===
<syntaxhighlight lang='bash'>
[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]
$ 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
=== logs ===
flask
<pre>
docker-compose logs -f
# Ctrl + c
</pre>


$ cat Dockerfile
== Package CLI Applications ==
FROM python:3.4-alpine
[https://www.cloudsavvyit.com/15713/how-to-use-docker-to-package-cli-applications/ How to Use Docker to Package CLI Applications]
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]


$ cat docker-compose.yml
== Stack ==
version: "3.5"
* https://www.composerize.com/
services:
* [https://youtu.be/-ttZjGBkLL8 Export Docker Container Settings as Docker Compose Stack], [https://github.com/Red5d/docker-autocompose docker-autocompose] (only x86)
  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:
== Docker app ==
  counter-net:
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.


volumes:
[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]
  counter-vol:


$ docker-compose up &
== Docker Swarm ==
* https://www.linux.com/learn/how-use-docker-machine-create-swarm-cluster
* [https://www.howtoforge.com/tutorial/ubuntu-docker-swarm-cluster/ How Setup and Configure Docker Swarm Cluster on Ubuntu]
* [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?]


$ docker container ls
== Security ==
* [https://cloudberry.engineering/article/dockerfile-security-best-practices/ Docker Security Best Practices from the Dockerfile]
* [https://www.cloudsavvyit.com/12631/how-to-secure-sensitive-data-with-docker-compose-secrets/ How to Secure Sensitive Data With Docker Compose Secrets]


$ docker network ls
== [https://mobyproject.org/ Moby Project] ==
NETWORK ID          NAME                    DRIVER              SCOPE
[https://www.infoworld.com/article/3193904/containers/what-is-dockers-moby-project.html What is Docker's Moby Project?]
2acef6dabde6        bridge                  bridge              local
 
a2d42bc482ff        counterapp_counter-net  bridge              local
== Windows container ==
e1e093b64282        host                    host                local
[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?]
7ecd0a6a9ebd        none                    null                local
 
== When Not to Use Docker ==
[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]
 
= GUI/TUI interface manager =
== [https://github.com/moncho/dry Dry] ==
[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.


# Open the browser http://localhost:5000
== LazyDocker (TUI) ==
$ docker-compose ps
[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]
      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
It works on ARM devices too.
$ docker-compose ps
# We can see stopping a Compose app does not delete the application


$ docker container ls -a
== Dockly (TUI) ==
$ docker-compose rm    # delete a stopped Compose app
[https://www.ostechnix.com/dockly-manage-docker-containers-from-terminal/ Dockly – Manage Docker Containers From Terminal]
                        # 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,
== DockStation ==
# and have them reflected immediately in the app.
It is not open source. It works with remote Docker containers.
$ 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
* [https://github.com/DockStation/dockstation DockStation]
</syntaxhighlight>
* [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.how2shout.com/tools/4-best-docker-gui-tools-to-manage-containers-graphically.html 4 Best Docker GUI tools to manage containers graphically] 2019


== DockSTARTer: get started with home server apps running in Docker ==
* https://dockstarter.com/
* [https://www.makeuseof.com/tag/setup-linux-media-server/ How to Set Up a Linux Media Server in Under One Hour]


=== Docker-Compose persistent data MySQL ===
== [https://portainer.io/ Portainer]* (nice) ==
https://stackoverflow.com/questions/39175194/docker-compose-persistent-data-mysql
<ul>
 
<li>[https://github.com/portainer/portainer/issues/5406 Hardware minimum requirements] 100MB RAM. That's why 1GB ram of Raspberry Pi works fine.
=== Connect to Docker daemon over ssh using docker-compose ===
<li>[https://docs.portainer.io/start/install/server/docker/linux Install], [https://docs.portainer.io/ Documentation]
[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]
<pre>
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 </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>
<li>[https://dbtechreviews.com/2020/08/update-portainer-to-version-2-0-super-easy/ Update Portainer to Version 2.0 – Super Easy!]. When the first time accessing http://localhost:9000, you need to create a password (at least 8 characters long) for the default user "admin".
{{Pre}}
$ docker volume create portainer_data
$ docker run -d -p 9000:9000 -p 8000:8000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
</pre>
* [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>Update from 2.11 to 2.13 (The password must be at least 12 characters long)
<ul>
<li>Step 1: [https://dbtechreviews.com/2021/08/how-to-update-portainer-to-the-newest-version/ How to Update Portainer to the Newest Version]
<pre>
sudo docker stop portainer && sudo docker rm portainer
docker pull portainer/portainer-ce:latest
</pre>
</li>
<li>Step 2: [https://docs.portainer.io/start/upgrade/docker Upgrading on Docker Standalone]
{{Pre}}
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>
</li>
</ul>
</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


=== Dockerfile + docker-compose ===
=== Templates ===
[https://stackoverflow.com/a/29487120 Docker Compose vs. Dockerfile - which is better?]  
* [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)
The Compose file describes the container in its running state, leaving the details on how to build the container to Dockerfiles.
* [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]
* [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
** 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)
** Alternative: [https://github.com/Taisun-Docker/taisun taisun]


=== How to deploy on remote Docker hosts with docker-compose ===
== Yacht ==
[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]
* https://yacht.sh/Installation/yacht/
* [https://youtu.be/KstIS5DstTE Yacht Installed on Docker - Portainer Alternative] (video)


== Package CLI Applications ==
== cockpit-docker ==
[https://www.cloudsavvyit.com/15713/how-to-use-docker-to-package-cli-applications/ How to Use Docker to Package CLI Applications]
* [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


== Stack ==
sudo systemctl restart cockpit
* https://www.composerize.com/
</pre>
* [https://youtu.be/-ttZjGBkLL8 Export Docker Container Settings as Docker Compose Stack], [https://github.com/Red5d/docker-autocompose docker-autocompose] (only x86)


== Docker app ==
== [https://github.com/crosbymichael/dockerui DockerUI] (Deprecated, Development continues at Portainer) ==
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.
https://github.com/kevana/ui-for-docker. A quick start:
# Run:  <syntaxhighlight lang='bash'>
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://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]
Note: Anyone in the local network can access the website without any authentication.


== Docker Swarm ==
== Rancher ==
* https://www.linux.com/learn/how-use-docker-machine-create-swarm-cluster
* 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-docker-swarm-cluster/ How Setup and Configure Docker Swarm Cluster on Ubuntu]
* [https://www.howtoforge.com/tutorial/ubuntu-rancher-docker-container-manager/ How to Manage Docker Containers with Rancher on Ubuntu 16.04]
* [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?]
* [https://hackernoon.com/creating-a-scalable-application-using-docker-rancher-rancheros-cattle-5feb83a3e743 Creating A Scalable Application Using Docker + Rancher + RancherOs + Cattle]
* Initial setup video https://youtu.be/1EMW1y7529Y
* Training from Rancher Labs https://youtu.be/8K14A_CZFdI. It seems Rancher is complicated but powerful. The whole operation is like Amazon Cloud.
* [https://gist.github.com/lmmendes/fbed32a452cf02d2a1095658795cb3d2 Running Rancher locally (with two hosts) using MacOS Docker and VirtualBox]
* To allow UDP port
<syntaxhighlight lang='bash'>
$ sudo apt-get install ufw
$ 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


== Security ==
== [https://github.com/tobegit3hub/seagull Seagull] ==
* [https://cloudberry.engineering/article/dockerfile-security-best-practices/ Docker Security Best Practices from the Dockerfile]
https://youtu.be/TuT5gb8oRw8
* [https://www.cloudsavvyit.com/12631/how-to-secure-sensitive-data-with-docker-compose-secrets/ How to Secure Sensitive Data With Docker Compose Secrets]


== [https://mobyproject.org/ Moby Project] ==
<pre>
[https://www.infoworld.com/article/3193904/containers/what-is-dockers-moby-project.html What is Docker's Moby Project?]
docker run -d -p 127.0.0.1:10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull
</pre>


== Windows container ==
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.
[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?]


== When Not to Use Docker ==
That is, the tool is suitable for home use.
[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]
 
== [https://kitematic.com/ 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 [https://www.r-bloggers.com/share-your-shiny-apps-with-docker-and-kitematic/ Share your Shiny Apps with Docker and Kitematic!]
 
== [https://github.com/shipyard/shipyard Shipyard] (retired) ==
* [https://www.sumologic.com/blog/code/managing-containers-docker-shipyard/ Managing Containers with Docker Shipyard]
* Three alternatives:
** [http://rancher.com/ Rancher]
** [https://github.com/kevana/ui-for-docker Docker UI]
** [https://portainer.io/ Portainer]
 
== 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]


= Applications =
= Applications =
[[Docker_Applications|Docker Applications]]
[[Docker_Applications|Docker Applications]]
== CasaOS ==
* https://casaos.io/
* [https://youtu.be/FwJByjTdKks Revisiting CasaOS After A Few Months] 2022-6-14


= Orchestrator =
= Orchestrator =
Line 2,618: Line 2,743:
/dev/sda6      108M  52K  99M  1% /usr/share/oem
/dev/sda6      108M  52K  99M  1% /usr/share/oem
core@CoreBM1 ~ $ free -m
core@CoreBM1 ~ $ free -m
             total      used      free    shared    buffers    cached
             total      used      free    shared    buffers    cached
Mem:          2713        187      2525          0          9        109
Mem:          2713        187      2525          0          9        109
-/+ buffers/cache:        68      2644
-/+ buffers/cache:        68      2644
Swap:            0          0          0
Swap:            0          0          0
core@CoreBM1 ~ $ lsb_release -a
core@CoreBM1 ~ $ lsb_release -a
-bash: lsb_release: command not found
-bash: lsb_release: command not found
core@CoreBM1 ~ $ docker pull ubuntu
core@CoreBM1 ~ $ docker pull ubuntu
Using default tag: latest
Using default tag: latest
latest: Pulling from library/ubuntu
latest: Pulling from library/ubuntu
f069f1d21059: Pull complete
f069f1d21059: Pull complete
ecbeec5633cf: Pull complete
ecbeec5633cf: Pull complete
ea6f18256d63: Pull complete
ea6f18256d63: Pull complete
54bde7b02897: Pull complete
54bde7b02897: Pull complete
Digest: sha256:bbfd93a02a8487edb60f20316ebc966ddc7aa123c2e609185450b96971020097
Digest: sha256:bbfd93a02a8487edb60f20316ebc966ddc7aa123c2e609185450b96971020097
Status: Downloaded newer image for ubuntu:latest
Status: Downloaded newer image for ubuntu:latest
core@CoreBM1 ~ $ docker images
core@CoreBM1 ~ $ docker images
REPOSITORY          TAG                IMAGE ID            CREATED            SIZE
REPOSITORY          TAG                IMAGE ID            CREATED            SIZE
ubuntu              latest              0f192147631d        7 days ago          132.7 MB
ubuntu              latest              0f192147631d        7 days ago          132.7 MB
core@CoreBM1 ~ $
core@CoreBM1 ~ $
</syntaxhighlight>
</syntaxhighlight>
 
== CoreOS cluster discovery ==
https://coreos.com/os/docs/latest/cluster-discovery.html
 
== etcd ==
* https://coreos.com/etcd/
 
== fleet ==
* https://coreos.com/using-coreos/clustering/
 
= TryGhost =
https://github.com/TryGhost/Ghost
 
= 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]


== CoreOS cluster discovery ==
= Self-hosting =
https://coreos.com/os/docs/latest/cluster-discovery.html
[https://www.reddit.com/r/selfhosted/comments/uvq1x3/tools_and_resources_for_selfhosting/ Tools and Resources for Self-Hosting]
 
== etcd ==
* https://coreos.com/etcd/
 
== fleet ==
* https://coreos.com/using-coreos/clustering/
 
= TryGhost =
https://github.com/TryGhost/Ghost
 
= 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]


= Resource =
= Resource =
Line 2,685: Line 2,813:
* http://training.play-with-docker.com/, [https://training.play-with-docker.com/alacart/ A full list of labs]
* 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/
* 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
* 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 ==
== Alternatives ==

Revision as of 09:32, 6 September 2022

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

Docker Desktop

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

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

https://docs.docker.com/engine/installation/linux/docker-ce/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-vm.png

$ # 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.

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

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

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

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

<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

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

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.

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

$ sudo docker logs -f nostalgic_morse

Clear Logs of Running Docker Containers

How to Clear Logs of Running Docker Containers

Looking at our Web Application Container's processes

$ sudo docker top nostalgic_morse

Inspecting our Web Application Container

$ sudo 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 & stdin

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

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

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

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 .

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

Google cloud registry

Using google cloud registry for private docker images

Dockerfile

  • 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
  • rocker (R and RStudio)
  • Bioconductor

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

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

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

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 --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.

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": ["XXX.XX.XX.XX", "YYY.YY.YY.YY"]
}

Then restart the docker service: sudo service docker restart

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

Authentication: Authelia

Additional Self-Hosted Security with Authelia on NGINX Proxy Manager (video)

GUI apps

Docker-OSX

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

Pruning unused resources

  • 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 images
docker images prune # unused image layers
  • Prune volumes
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
  • Prune everything
docker system prune

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 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

Docker Compose <docker-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).

Download binary

wget https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-linux-x86_64
sudo mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

Composerize

Convert Docker Run Commands Into Docker-Compose Files

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,

docker-compose down

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


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

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

How can I run a docker windows container on osx?

When Not to Use Docker

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

GUI/TUI interface manager

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)

LazyDocker: New Docker And Docker Compose Terminal UI, Github

It works on ARM devices too.

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)

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

Orchestrator

Kubernete

Kubernete vs Docker swarm

k3s: Lightweight Kubernetes

Run Kubernetes on a Raspberry Pi with k3s

Other containers

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 $ singularity build
$ 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

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

Resource

Internet

Books

Blogs

Tips/trouble shooting

Play with Docker (PWD)

Alternatives

The 9 Best Docker Alternatives for Container Management

Serverless computing