Last active
September 7, 2017 17:32
-
-
Save igoralves1/82f15cf6cef170441569f5da51eb3f8d to your computer and use it in GitHub Desktop.
Get Docker CE for Ubuntu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#https://github.com/tianon/docker-brew-ubuntu-core/blob/a2573609340194bf33712c1fa2dc4de8f9b70ca2/trusty/Dockerfile | |
Docs @ Docker | |
https://store.docker.com/images/docker-docs | |
DevOps Tools | |
https://store.docker.com/search?category=tools&source=verified&type=image | |
https://www.lynda.com/Docker-tutorials/Docker-Basics/485649-2.html?utm_source=google&utm_medium=cpc&utm_campaign=l1-US-Search-Dev-Docker-MBM&cid=mbm-docker_basics&utm_content=188694096608&utm_term=%2Bdocker%20%2Bbasics&src=go-pa&veh=skwd-179185467675_pcrid_188694096608_pkw_%2Bdocker%20%2Bbasics_pmt_b_pdv_c_ext__plc__trg__agid_37975019741_cmid_791016461_adp_1t1_net_g&lpk35=9137 | |
Apache and PHP on Docker | |
https://writing.pupius.co.uk/apache-and-php-on-docker-44faef716150 | |
//https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/ | |
//NOTE:If error reported in UBUNTU => https://unix.stackexchange.com/questions/326427/ubuntu-16-10-showing-error-after-booting-sorry-ubuntu-16-10-has-experienced-a | |
To get started with Docker CE on Ubuntu, make sure you meet the prerequisites, then install Docker. | |
Note: | |
Docker EE customers | |
To install Docker Enterprise Edition (Docker EE), go to Get Docker EE for Ubuntu instead of this topic. | |
To learn more about Docker EE, see Docker Enterprise Edition. | |
Prerequisites | |
Docker EE customers | |
To install Docker Enterprise Edition (Docker EE), go to Get Docker EE for Ubuntu instead of this topic. | |
To learn more about Docker EE, see Docker Enterprise Edition. | |
OS requirements | |
To install Docker CE, you need the 64-bit version of one of these Ubuntu versions: | |
Zesty 17.04 | |
Xenial 16.04 (LTS) | |
Trusty 14.04 (LTS) | |
Docker CE is supported on Ubuntu on x86_64, armhf, and s390x (IBM z Systems) architectures. | |
s390x limitations: System Z is only supported on Ubuntu Xenial and Zesty. | |
Uninstall old versions | |
Older versions of Docker were called docker or docker-engine. If these are installed, uninstall them: | |
$ sudo apt-get remove docker docker-engine docker.io | |
It’s OK if apt-get reports that none of these packages are installed. | |
The contents of /var/lib/docker/, including images, containers, volumes, and networks, are preserved. The Docker CE package is now called docker-ce. | |
Recommended extra packages for Trusty 14.04 | |
Unless you have a strong reason not to, install the linux-image-extra-* packages, which allow Docker to use the aufs storage drivers. | |
$ sudo apt-get update | |
$ sudo apt-get install \ | |
linux-image-extra-$(uname -r) \ | |
linux-image-extra-virtual | |
For Ubuntu 16.04 and higher, the Linux kernel includes support for OverlayFS, and Docker CE will use the overlay2 storage driver by default. | |
Install Docker CE | |
You can install Docker CE in different ways, depending on your needs: | |
Most users set up Docker’s repositories and install from them, for ease of installation and upgrade tasks. This is the recommended approach. | |
Some users download the DEB package and install it manually and manage upgrades completely manually. This is useful in situations such as installing Docker on air-gapped systems with no access to the internet. | |
In testing and development environments, some users choose to use automated convenience scripts to install Docker. | |
Install using the repository | |
Before you install Docker CE for the first time on a new host machine, you need to set up the Docker repository. Afterward, you can install and update Docker from the repository. | |
Set up the repository | |
Update the apt package index: | |
$ sudo apt-get update | |
Install packages to allow apt to use a repository over HTTPS: | |
$ sudo apt-get install \ | |
apt-transport-https \ | |
ca-certificates \ | |
curl \ | |
software-properties-common | |
Add Docker’s official GPG key: | |
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - | |
Verify that the key fingerprint is 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88. | |
$ sudo apt-key fingerprint 0EBFCD88 | |
pub 4096R/0EBFCD88 2017-02-22 | |
Key fingerprint = 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 | |
uid Docker Release (CE deb) <[email protected]> | |
sub 4096R/F273FCD8 2017-02-22 | |
Use the following command to set up the stable repository. You always need the stable repository, even if you want to install builds from the edge or testing repositories as well. To add the edge or testing repository, add the word edge or testing (or both) after the word stable in the commands below. | |
Note: The lsb_release -cs sub-command below returns the name of your Ubuntu distribution, such as xenial. Sometimes, in a distribution like Linux Mint, you might have to change $(lsb_release -cs) to your parent Ubuntu distribution. For example, if you are using Linux Mint Rafaela, you could use trusty. | |
amd64: | |
$ sudo add-apt-repository \ | |
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \ | |
$(lsb_release -cs) \ | |
stable" | |
armhf: | |
$ sudo add-apt-repository \ | |
"deb [arch=armhf] https://download.docker.com/linux/ubuntu \ | |
$(lsb_release -cs) \ | |
stable" | |
s390x: | |
$ sudo add-apt-repository \ | |
"deb [arch=s390x] https://download.docker.com/linux/ubuntu \ | |
$(lsb_release -cs) \ | |
stable" | |
Note: Starting with Docker 17.06, stable releases are also pushed to the edge and testing repositories. | |
Learn about stable and edge channels. | |
Install Docker CE | |
Update the apt package index. | |
$ sudo apt-get update | |
Install the latest version of Docker CE, or go to the next step to install a specific version. Any existing installation of Docker is replaced. | |
$ sudo apt-get install docker-ce | |
Got multiple Docker repositories? | |
If you have multiple Docker repositories enabled, installing or updating without specifying a version in the apt-get install or apt-get update command will always install the highest possible version, which may not be appropriate for your stability needs. | |
On production systems, you should install a specific version of Docker CE instead of always using the latest. This output is truncated. List the available versions. | |
$ apt-cache madison docker-ce | |
docker-ce | 17.06.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages | |
The contents of the list depend upon which repositories are enabled. Choose a specific version to install. The second column is the version string. The third column is the repository name, which indicates which repository the package is from and by extension its stability level. To install a specific version, append the version string to the package name and separate them by an equals sign (=): | |
$ sudo apt-get install docker-ce=<VERSION> | |
The Docker daemon starts automatically. | |
Verify that Docker CE is installed correctly by running the hello-world image. | |
$ sudo docker run hello-world | |
This command downloads a test image and runs it in a container. When the container runs, it prints an informational message and exits. | |
Docker CE is installed and running. You need to use sudo to run Docker commands. Continue to Linux postinstall to allow non-privileged users to run Docker commands and for other optional configuration steps. | |
Upgrade Docker CE | |
To upgrade Docker CE, first run sudo apt-get update, then follow the installation instructions, choosing the new version you want to install. | |
Result =======> | |
ila@ila:~$ sudo docker run hello-world | |
Unable to find image 'hello-world:latest' locally | |
latest: Pulling from library/hello-world | |
b04784fba78d: Pull complete | |
Digest: sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f | |
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. | |
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 | |
Share images, automate workflows, and more with a free Docker ID: | |
https://cloud.docker.com/ | |
For more examples and ideas, visit: | |
https://docs.docker.com/engine/userguide/ | |
//Confirm that Docker is instaled | |
ila@ila:~$ docker | |
Usage: docker COMMAND | |
A self-sufficient runtime for containers | |
Options: | |
--config string Location of client config files (default "/home/ila/.docker") | |
-D, --debug Enable debug mode | |
--help Print usage | |
-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/ila/.docker/ca.pem") | |
--tlscert string Path to TLS certificate file (default "/home/ila/.docker/cert.pem") | |
--tlskey string Path to TLS key file (default "/home/ila/.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 | |
stack Manage Docker stacks | |
swarm Manage Swarm | |
system Manage Docker | |
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. | |
================================================================================================================================== | |
Post-installation steps for Linux | |
ila@ila:~$ docker ps | |
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.30/containers/json: dial unix /var/run/docker.sock: connect: permission denied | |
//===>If I use SUDO it works. | |
ila@ila:~$ sudo docker ps | |
[sudo] password for ila: | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
//===>That means Root is allways needed. | |
Manage Docker as a non-root user | |
The docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root and other users can only access it using sudo. The docker daemon always runs as the root user. | |
If you don’t want to use sudo when you use the docker command, create a Unix group called docker and add users to it. When the docker daemon starts, it makes the ownership of the Unix socket read/writable by the docker group. | |
Warning: The docker group grants privileges equivalent to the root user. For details on how this impacts security in your system, see Docker Daemon Attack Surface. | |
To create the docker group and add your user: | |
Create the docker group. | |
$ sudo groupadd docker | |
//===>Create a group docker. Maybe it alread exists. | |
ila@ila:~$ sudo groupadd docker | |
groupadd: group 'docker' already exists | |
//===>check what GROUPS ila is IN | |
ila@ila:~$ sudo groups ila | |
ila : ila adm cdrom sudo dip plugdev lpadmin sambashare | |
Add your user to the docker group. | |
$ sudo usermod -aG docker $USER | |
//===>Add ils to docker group | |
ila@ila:~$ sudo usermod -aG docker ila | |
//===>Check again | |
ila@ila:~$ sudo groups ila | |
ila : ila adm cdrom sudo dip plugdev lpadmin sambashare docker | |
//===>If you try to use docker again without ROOT will faill => permission denied | |
ila@ila:~$ docker ps | |
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.30/containers/json: dial unix /var/run/docker.sock: connect: permission denied | |
Log out and log back in so that your group membership is re-evaluated. | |
//===>If you try to use docker again without ROOT: It works | |
ila@ila:~$ docker ps | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
//==>There is no container at this point. | |
If testing on a virtual machine, it may be necessary to restart the virtual machine for changes to take affect. | |
On a desktop Linux environment such as X Windows, log out of your session completely and then log back in. | |
Verify that you can run docker commands without sudo. | |
$ docker run hello-world | |
//==> | |
ila@ila:~$ 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. | |
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 | |
Share images, automate workflows, and more with a free Docker ID: | |
https://cloud.docker.com/ | |
For more examples and ideas, visit: | |
https://docs.docker.com/engine/userguide/ | |
This command downloads a test image and runs it in a container. When the container runs, it prints an informational message and exits. | |
Configure Docker to start on boot | |
Most current Linux distributions (RHEL, CentOS, Fedora, Ubuntu 16.04 and higher) use systemd to manage which services start when the system boots. Ubuntu 14.10 and below use upstart. | |
systemd | |
$ sudo systemctl enable docker | |
ila@ila:/usr/bin$ sudo systemctl enable docker | |
Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install. | |
Executing: /lib/systemd/systemd-sysv-install enable docker | |
To disable this behavior, use disable instead. | |
$ sudo systemctl disable docker | |
If you need to add an HTTP Proxy, set a different directory or partition for the Docker runtime files, or make other customizations, see customize your systemd Docker daemon options.//https://docs.docker.com/engine/admin/systemd/ | |
upstart | |
Docker is automatically configured to start on boot using upstart. To disable this behavior, use the following command: | |
$ echo manual | sudo tee /etc/init/docker.override | |
chkconfig | |
$ sudo chkconfig docker on | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#use-a-different-storage-engine | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#troubleshooting | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#kernel-compatibility | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#cannot-connect-to-the-docker-daemon | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#ip-forwarding-problems | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#dns-resolver-found-in-resolvconf-and-containers-cant-use-it | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#specify-dns-servers-for-docker | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#allow-access-to-the-remote-api-through-a-firewall | |
https://docs.docker.com/engine/installation/linux/linux-postinstall/#your-kernel-does-not-support-cgroup-swap-limit-capabilities | |
================================================================================================================================== | |
Docker Engine user guide | |
https://docs.docker.com/engine/userguide/ | |
This guide helps users learn how to use Docker Engine. | |
Learn by example | |
Network containers | |
Manage data in containers | |
Samples | |
Get started | |
Work with images | |
Best practices for writing Dockerfiles | |
Create a base image | |
Image management | |
Manage storage drivers | |
Understand images, containers, and storage drivers | |
Select a storage driver | |
AUFS storage in practice | |
Btrfs storage in practice | |
Device Mapper storage in practice | |
OverlayFS storage in practice | |
ZFS storage in practice | |
Configure networks | |
Understand Docker container networks | |
Embedded DNS server in user-defined networks | |
Get started with multi-host networking | |
Work with network commands | |
Work with the default network | |
Understand container communication | |
Legacy container links | |
Binding container ports to the host | |
Build your own bridge | |
Configure container DNS | |
Customize the docker0 bridge | |
IPv6 with Docker | |
================================================================================================================================= | |
Play with Docker Classroom | |
//http://training.play-with-docker.com/ | |
Docker for Developers | |
http://training.play-with-docker.com/dev-landing/ | |
================================================================================================================================= | |
Docker for Developers Stage 1 | |
This stage will | |
Get you familiar with the core concepts of Docker | |
Show you how to build and deploy basic applications | |
Self-guided in-browser tutorials | |
Hello World | |
Your First Linux Container | |
Developing a Simple Web App | |
Deploying a Multi-Service App in Docker Swarm Mode | |
Deploying a Multi-Service App in Docker Swarm Mode | |
http://training.play-with-docker.com/helloworld/ | |
Hello World | |
Prerequisites | |
$ docker container 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. | |
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 | |
Share images, automate workflows, and more with a free Docker ID: | |
https://cloud.docker.com/ | |
For more examples and ideas, visit: | |
https://docs.docker.com/engine/userguide/ | |
1.0 Running your first container <============================================================================================== | |
Now that you have everything setup, it’s time to get our hands dirty. In this section, you are going to run an Alpine Linux container (a lightweight linux distribution) on your system and get a taste of the docker container run command. | |
To get started, let’s run the following in our terminal: | |
$ docker image pull alpine | |
The pull command fetches the alpine image from the Docker registry and saves it in our system. In this case the registry is Docker Store. You can change the registry, but that’s a different lab. | |
You can use the docker image command to see a list of all images on your system. | |
ila@ila:~$ docker image ls | |
REPOSITORY TAG IMAGE ID CREATED SIZE | |
elasticsearch latest 4255fc97fa5f 6 days ago 316MB | |
nginx latest b8efb18f159b 7 days ago 107MB | |
mongo latest 6833171fe0ad 7 days ago 359MB | |
alpine latest 7328f6f8b418 5 weeks ago 3.97MB | |
hello-world latest 1815c82652c0 7 weeks ago 1.84kB | |
http://training.play-with-docker.com/alpine/ | |
1.1 Docker Container Run <====================================================================================================== | |
Great! Let’s now run a Docker container based on this image. To do that you are going to use the docker container run command. | |
ila@ila:~$ docker container run alpine ls -l | |
total 52 | |
drwxr-xr-x 2 root root 4096 Jun 25 17:52 bin | |
drwxr-xr-x 5 root root 340 Aug 2 20:27 dev | |
drwxr-xr-x 14 root root 4096 Aug 2 20:27 etc | |
drwxr-xr-x 2 root root 4096 Jun 25 17:52 home | |
drwxr-xr-x 5 root root 4096 Jun 25 17:52 lib | |
What happened? Behind the scenes, a lot of stuff happened. | |
1 - When you call run, the Docker client finds the image (alpine in this case), | |
2 - creates the container and then | |
3 - runs a command in that container. | |
When you run docker container run alpine, you provided a command (ls -l), so Docker started the command specified and you saw the listing. | |
Let’s try something more exciting: | |
ila@ila:~$ docker container run alpine echo "hello from alpine" | |
hello from alpine | |
OK, that’s some actual output. In this case, the Docker client dutifully ran the echo command in our alpine container and then exited it. If you’ve noticed, all of that happened pretty quickly. Imagine booting up a virtual machine, running a command and then killing it. Now you know why they say containers are fast! | |
//==>Note: | |
Running proccesses: | |
1-boot the container | |
2-run a echo command | |
3-kill the container | |
Try another command. | |
ila@ila:~$ docker container run alpine /bin/sh | |
Wait, nothing happened! Is that a bug? Well, no. | |
These interactive shells will EXIT after running any scripted commands, | |
unless they are run in an INTERACTIVE TERMINAL - so for this example TO NOT EXIT, | |
you need to docker container run -it alpine /bin/sh | |
ila@ila:~$ docker container run -it alpine /bin/sh | |
/ # ls | |
bin dev etc home lib media mnt proc root run sbin srv sys tmp usr var | |
/ # | |
//==>Note: | |
Note the /# saying it is a ROOT inside the interactive terminal. | |
You are now inside the container shell and you can try out a few commands: | |
like ls -l, | |
uname -a | |
and others. | |
Exit out of the container by giving the # exit command. | |
/ # uname -a | |
Linux e46bc24f5827 4.10.0-28-generic #32-Ubuntu SMP Fri Jun 30 05:32:18 UTC 2017 x86_64 Linux | |
/ # exit | |
ila@ila:~$ | |
ila@ila:~$ docker container run -it alpine /bin/sh | |
/ # ps | |
PID USER TIME COMMAND | |
1 root 0:00 /bin/sh | |
8 root 0:00 ps | |
/ # exit | |
ila@ila:~$ ps | |
PID TTY TIME CMD | |
2534 pts/0 00:00:00 bash | |
4502 pts/0 00:00:00 ps | |
ila@ila:~$ | |
Ok, now it’s time to see the docker container ls command. | |
The docker container ls command shows you all containers that are currently running. | |
ila@ila:~$ docker container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
Since no containers are running, you see a blank line. Let’s try a more useful variant: docker container ls -a | |
ila@ila:~$ docker container ls -a | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
531fb8eab495 alpine "/bin/sh" 4 minutes ago Exited (0) 4 minutes ago fervent_bartik | |
b35d30f0e7f9 alpine "/bin/sh" 5 minutes ago Exited (0) 4 minutes ago unruffled_golick | |
e46bc24f5827 alpine "/bin/sh" 11 minutes ago Exited (0) 5 minutes ago nervous_banach | |
a547046a771f alpine "/bin/sh" 11 minutes ago Exited (0) 11 minutes ago pedantic_goldberg | |
f0c755f6954a alpine "/bin/sh" 13 minutes ago Exited (0) 13 minutes ago dazzling_turing | |
ac2388a5a6b8 alpine "echo 'hello from ..." 18 minutes ago Exited (0) 18 minutes ago wizardly_darwin | |
8c27fa3269f8 alpine "ls -l" 20 minutes ago Exited (0) 20 minutes ago clever_joliot | |
65a3b65a198f alpine "ls -l" 25 minutes ago Exited (0) 25 minutes ago vibrant_meitner | |
3f7c396855a8 alpine "ls" 25 minutes ago Exited (0) 25 minutes ago festive_volhard | |
a065aff18f8e alpine "ll" 26 minutes ago Created lucid_perlman | |
6a6d5b817a40 alpine "/bin/sh" 26 minutes ago Exited (0) 26 minutes ago priceless_hopper | |
f1cf3c5fd876 alpine "ls -l" 27 minutes ago Exited (0) 27 minutes ago practical_swartz | |
7558a0012533 hello-world "/hello" 34 minutes ago Exited (0) 34 minutes ago competent_knuth | |
af3b72118c2b elasticsearch "/docker-entrypoin..." 3 hours ago Exited (143) 2 hours ago happy_kilby | |
fd2472026a1c mongo "docker-entrypoint..." 3 hours ago Exited (0) 2 hours ago some-mongo | |
1dac70ff39d3 nginx "nginx -g 'daemon ..." 4 hours ago Exited (0) 2 hours ago some-nginx | |
80e4da08b194 hello-world "/hello" 4 hours ago Exited (0) 4 hours ago admiring_almeida | |
5e81841bbb1c hello-world "/hello" 4 hours ago Exited (0) 4 hours ago romantic_leavitt | |
654f620a47d2 hello-world "/hello" 5 hours ago Exited (0) 5 hours ago silly_newton | |
35982b116ce1 hello-world "/hello" 6 hours ago Exited (0) 6 hours ago epic_shannon | |
What you see above is a list of all containers that you ran. Notice that the STATUS column shows that these containers exited a few minutes ago. You’re probably wondering if there is a way to run more than just one command in a container. Let’s try that now: | |
docker container run -it alpine /bin/sh | |
ila@ila:~$ docker container run -it alpine /bin/sh | |
/ # ls | |
bin dev etc home lib media mnt proc root run sbin srv sys tmp usr var | |
/ # uname -a | |
Linux 8ecc3878a1cd 4.10.0-28-generic #32-Ubuntu SMP Fri Jun 30 05:32:18 UTC 2017 x86_64 Linux | |
/ # | |
Running the run command with the -it flags attaches us to an interactive tty in the container. Now you can run as many commands in the container as you want. Take some time to run your favorite commands. | |
//==>Note: | |
1 - To scape from shell use $ exit or ctrl+d | |
2 - While running the terminal with -it we can open another terminal and type: | |
$ docker ps | |
ila@ila:~$ docker ps | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
8ecc3878a1cd alpine "/bin/sh" 15 hours ago Up 15 hours xenodochial_hoover | |
ila@ila:~$ | |
We will see that there is a docker container opened already. In this case the image's name is alpine. | |
That concludes a whirlwind tour of the docker container run command which would most likely be the command you’ll use most often. It makes sense to spend some time getting comfortable with it. To find out more about run, use docker container run --help to see a list of all flags it supports. As you proceed further, we’ll see a few more variants of docker container run. | |
1.2 Terminology <=============================================================================================================== | |
In the last section, you saw a lot of Docker-specific jargon which might be confusing to some. So before you go further, let’s clarify some terminology that is used frequently in the Docker ecosystem. | |
1 ==> Images - The file system and configuration of our application which are used to create containers. To find out more about a Docker image, run docker image inspect alpine. In the demo above, you used the docker image pull command to download the alpine image. When you executed the command docker container run hello-world, it also did a docker image pull behind the scenes to download the hello-world image. | |
ila@ila:~$ dk image inspect hello-world | |
[ | |
{ | |
"Id": "sha256:1815c82652c03bfd8644afda26fb184f2ed891d921b20a0703b46768f9755c57", | |
"RepoTags": [ | |
"hello-world:latest" | |
], | |
"RepoDigests": [ | |
"hello-world@sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f" | |
], | |
"Parent": "", | |
"Comment": "", | |
"Created": "2017-06-14T19:29:01.037740325Z", | |
"Container": "daea997c17c2861b425edaa87aa7556b4b2d1d4913d2b66014696f2ce340306b", | |
"ContainerConfig": { | |
"Hostname": "adc90845fac3", | |
"Domainname": "", | |
"User": "", | |
"AttachStdin": false, | |
"AttachStdout": false, | |
"AttachStderr": false, | |
"Tty": false, | |
"OpenStdin": false, | |
"StdinOnce": false, | |
"Env": [ | |
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" | |
], | |
"Cmd": [ | |
"/bin/sh", | |
"-c", | |
"#(nop) ", | |
"CMD [\"/hello\"]" | |
], | |
"ArgsEscaped": true, | |
"Image": "sha256:6e47ed59f6b5dbe00587d2a08e6972feaf9d10eee5a2b107099b4707e934c0c7", | |
"Volumes": null, | |
"WorkingDir": "", | |
"Entrypoint": null, | |
"OnBuild": null, | |
"Labels": {} | |
}, | |
"DockerVersion": "17.03.1-ce", | |
"Author": "", | |
"Config": { | |
"Hostname": "adc90845fac3", | |
"Domainname": "", | |
"User": "", | |
"AttachStdin": false, | |
"AttachStdout": false, | |
"AttachStderr": false, | |
"Tty": false, | |
"OpenStdin": false, | |
"StdinOnce": false, | |
"Env": [ | |
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" | |
], | |
"Cmd": [ | |
"/hello" | |
], | |
"ArgsEscaped": true, | |
"Image": "sha256:6e47ed59f6b5dbe00587d2a08e6972feaf9d10eee5a2b107099b4707e934c0c7", | |
"Volumes": null, | |
"WorkingDir": "", | |
"Entrypoint": null, | |
"OnBuild": null, | |
"Labels": {} | |
}, | |
"Architecture": "amd64", | |
"Os": "linux", | |
"Size": 1840, | |
"VirtualSize": 1840, | |
"GraphDriver": { | |
"Data": null, | |
"Name": "aufs" | |
}, | |
"RootFS": { | |
"Type": "layers", | |
"Layers": [ | |
"sha256:45761469c965421a92a69cc50e92c01e0cfa94fe026cdd1233445ea00e96289a" | |
] | |
} | |
} | |
] | |
2 ==> Containers - Running instances of Docker images — containers run the actual applications. A container includes an application and all of its dependencies. It shares the kernel with other containers, and runs as an isolated process in user space on the host OS. You created a container using docker run which you did using the alpine image that you downloaded. A list of running containers can be seen using the docker container ls command. | |
//==>Note: | |
ila@ila:~$ dk container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
AND | |
ila@ila:~$ dk ps | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
These 2 commands bring me back the same result. | |
3 ==> Docker daemon - The background service running on the host that manages building, running and distributing Docker containers. | |
4 ==> Docker client - The command line tool that allows the user to interact with the Docker daemon. | |
5 ==> Docker Store - Store is, among other things, a registry of Docker images. You can think of the registry as a directory of all available Docker images. You’ll be using this later in this tutorial. | |
https://store.docker.com/ | |
https://store.docker.com/search?q=&source=verified&type=image | |
https://stackoverflow.com/questions/19234831/where-are-docker-images-stored-on-the-host-machine | |
You can manually set the storage driver with the -s or --storage-driver= option to the Docker daemon. | |
https://forums.docker.com/t/how-do-i-change-the-docker-image-installation-directory/1169 | |
Where do images get pulled from by default? ==> Docker Store | |
Which command lists your Docker images? ==> docker image ls | |
Simple Web App | |
http://training.play-with-docker.com/webapps/ | |
================================================================================================================================= | |
2.0 Webapps with Docker | |
Great! So you have now looked at docker container run, played with a Docker container and also got the hang of some terminology. Armed with all this knowledge, you are now ready to get to the real stuff — deploying web applications with Docker. | |
2.1 Run a static website in a container <======================================================================================= | |
We’ll use Docker to run a static website in a container. | |
The website is based on an existing image. We’ll pull a Docker image from Docker Store, run the container, and see how easy it is to set up a web server. | |
The image that you are going to use is a single-page website that was already created for this demo and is available on the Docker Store as seqvence/static-site. You can download and run the image directly in one go using docker run as follows. | |
docker container run -d seqvence/static-site | |
ila@ila:~$ docker container run -d seqvence/static-site | |
Unable to find image 'seqvence/static-site:latest' locally | |
latest: Pulling from seqvence/static-site | |
fdd5d7827f33: Pull complete | |
a3ed95caeb02: Pull complete | |
716f7a5f3082: Pull complete | |
7b10f03a0309: Pull complete | |
aff3ab7e9c39: Pull complete | |
Digest: sha256:41b286105f913fb7a5fbdce28d48bc80f1c77e3c4ce1b8280f28129ae0e94e9e | |
Status: Downloaded newer image for seqvence/static-site:latest | |
ffa6033dddeb813f10983a3420a10e2b50fc8e714d14913498402acd0d294755 | |
//==>Note: As the image was not inside the Docker Store, it was downloaded form the remote Docker Hub https://hub.docker.com/r/seqvence/static-site/ | |
So, what happens when you run this command? | |
Since the image doesn’t exist on your Docker host, the Docker daemon first fetches it from the registry and then runs it as a container. | |
Now that the server is running, do you see the website? What port is it running on? And more importantly, how do you access the container directly from our host machine? | |
//==>Note: Run dk ps to check what containners is running: So seqvence/static-site is running. | |
ila@ila:~$ dk ps | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
ffa6033dddeb seqvence/static-site "/bin/sh -c 'cd /u..." 7 minutes ago Up 7 minutes 80/tcp, 443/tcp epic_poincare | |
Actually, you probably won’t be able to answer any of these questions yet! ☺ In this case, the client didn’t tell the Docker Engine to publish any of the ports, so you need to re-run the docker container run command to add this instruction. | |
Let’s re-run the command with some new flags to publish ports and pass your name to the container to customize the message displayed. We’ll use the -d option again to run the container in detached mode. | |
=> Detached Mode => Release the terminal and make Docker (or any others services) running in the background. https://stackoverflow.com/questions/34029680/docker-detached-mode | |
The opposite of detached mode is foreground mode. That is the default mode, when -d option is not used. In this mode, the console you are using to execute docker run will be attached to standard input, output and error. That means your console is attached to the container's process. | |
In detached mode, you can follow the standard output of your docker container with docker logs -f <container_ID>. | |
First, stop the container that you have just launched. In order to do this, we need the container ID. | |
Since we ran the container in detached mode, we don’t have to launch another terminal to do this. Run docker container ls to view the running containers. | |
ila@ila:~$ docker container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
ffa6033dddeb seqvence/static-site "/bin/sh -c 'cd /u..." 40 minutes ago Up 40 minutes 80/tcp, 443/tcp epic_poincare | |
Check out the CONTAINER ID column. You will need to use this CONTAINER ID value, a long sequence of characters, to identify the container you want to stop, and then to remove it. The example below provides the CONTAINER ID on our system; you should use the value that you see in your terminal. | |
ila@ila:~$ dk container stop ffa6033dddeb | |
ffa6033dddeb | |
ila@ila:~$ docker container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
ila@ila:~$ dk container rm ffa6033dddeb | |
ffa6033dddeb | |
ila@ila:~$ | |
Note: A cool feature is that you do not need to specify the entire CONTAINER ID. You can just specify a few starting characters and if it is unique among all the containers that you have launched, the Docker client will intelligently pick it up. | |
ila@ila:~$ docker container run --name static-site -e AUTHOR="igor" -d -P seqvence/static-site | |
c66fe62638aab85b5b70a0be3338364d1c3dcd7efd571b1aebcb1ff679884072 | |
In the above command: | |
-d will create a container with the process detached from our terminal | |
-P will publish all the exposed container ports to random ports on the Docker host | |
-e is how you pass environment variables to the container | |
--name allows you to specify a container name | |
AUTHOR is the environment variable name and Your Name is the value that you can pass | |
Now you can see the ports by running the docker container port command. | |
ila@ila:~$ dk container port static-site | |
443/tcp -> 0.0.0.0:32770 | |
80/tcp -> 0.0.0.0:32771 | |
OR | |
ila@ila:~$ docker container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
c66fe62638aa seqvence/static-site "/bin/sh -c 'cd /u..." 3 seconds ago Up 2 seconds 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp static-site | |
ifconfig | |
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 | |
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 | |
inet6 fe80::42:cbff:fec5:1cee prefixlen 64 scopeid 0x20<link> | |
ether 02:42:cb:c5:1c:ee txqueuelen 0 (Ethernet) | |
RX packets 12 bytes 456 (456.0 B) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 297 bytes 25070 (25.0 KB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 | |
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255 | |
inet6 fe80::47b:92d:dad9:dd0 prefixlen 64 scopeid 0x20<link> | |
ether 08:00:27:1f:0d:7d txqueuelen 1000 (Ethernet) | |
RX packets 106174 bytes 108401954 (108.4 MB) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 38544 bytes 5342653 (5.3 MB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 | |
inet 127.0.0.1 netmask 255.0.0.0 | |
inet6 ::1 prefixlen 128 scopeid 0x10<host> | |
loop txqueuelen 1000 (Local Loopback) | |
RX packets 536 bytes 42320 (42.3 KB) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 536 bytes 42320 (42.3 KB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
veth9646dee: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 | |
inet6 fe80::3cc0:8dff:fe9c:e572 prefixlen 64 scopeid 0x20<link> | |
ether 3e:c0:8d:9c:e5:72 txqueuelen 0 (Ethernet) | |
RX packets 12 bytes 624 (624.0 B) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 72 bytes 8420 (8.4 KB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
//==>Note: Must choose 80/tcp -> 0.0.0.0:32771. In this way doing http://172.17.0.1:32771. | |
This is what we see in the browser: | |
Hello igor! | |
This is being served from a docker | |
container running Nginx. | |
You can also run a second webserver at the same time, specifying a custom host port mapping to the container’s webserver. | |
docker container run --name static-site-2 -e AUTHOR="Your Name" -d -p 8888:80 seqvence/static-site | |
ila@ila:~$ dk container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
c66fe62638aa seqvence/static-site "/bin/sh -c 'cd /u..." 2 hours ago Up 2 hours 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp static-site | |
ila@ila:~$ docker container run --name static-site-2 -e AUTHOR="Igor 2" -d -p 8888:80 seqvence/static-site | |
6d8d23eb31f0e83d78d3b62b3441fa505f17180821475152ca8c85fab2d58e36 | |
ila@ila:~$ dk container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
6d8d23eb31f0 seqvence/static-site "/bin/sh -c 'cd /u..." 6 seconds ago Up 5 seconds 443/tcp, 0.0.0.0:8888->80/tcp static-site-2 | |
c66fe62638aa seqvence/static-site "/bin/sh -c 'cd /u..." 2 hours ago Up 2 hours 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp static-site | |
ila@ila:~$ ifconfig | |
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 | |
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 | |
inet6 fe80::42:cbff:fec5:1cee prefixlen 64 scopeid 0x20<link> | |
ether 02:42:cb:c5:1c:ee txqueuelen 0 (Ethernet) | |
RX packets 62 bytes 22006 (22.0 KB) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 351 bytes 30133 (30.1 KB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 | |
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255 | |
inet6 fe80::47b:92d:dad9:dd0 prefixlen 64 scopeid 0x20<link> | |
ether 08:00:27:1f:0d:7d txqueuelen 1000 (Ethernet) | |
RX packets 106849 bytes 108558504 (108.5 MB) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 39159 bytes 5469477 (5.4 MB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 | |
inet 127.0.0.1 netmask 255.0.0.0 | |
inet6 ::1 prefixlen 128 scopeid 0x10<host> | |
loop txqueuelen 1000 (Local Loopback) | |
RX packets 571 bytes 54783 (54.7 KB) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 571 bytes 54783 (54.7 KB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
veth9646dee: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 | |
inet6 fe80::3cc0:8dff:fe9c:e572 prefixlen 64 scopeid 0x20<link> | |
ether 3e:c0:8d:9c:e5:72 txqueuelen 0 (Ethernet) | |
RX packets 62 bytes 22874 (22.8 KB) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 126 bytes 13483 (13.4 KB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
vethe779cb1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 | |
inet6 fe80::90b4:f4ff:fe17:a1e6 prefixlen 64 scopeid 0x20<link> | |
ether 92:b4:f4:17:a1:e6 txqueuelen 0 (Ethernet) | |
RX packets 0 bytes 0 (0.0 B) | |
RX errors 0 dropped 0 overruns 0 frame 0 | |
TX packets 28 bytes 3944 (3.9 KB) | |
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 | |
//==>Note: | |
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 | |
So doker has its Ip = 172.17.0.1 and 0.0.0.0:8888->80/tcp | |
Making URL=http://172.17.0.1:8888/ | |
Hello Igor 2! | |
This is being served from a docker | |
container running Nginx. | |
===========> Important | |
To deploy this on a real server you would just need to install Docker, and run the above docker command(as in this case you can see the AUTHOR is Docker which we passed as an environment variable). | |
<=========================================================== | |
Let’s stop and remove the containers since you won’t be using them anymore. | |
ila@ila:~$ dk container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
6d8d23eb31f0 seqvence/static-site "/bin/sh -c 'cd /u..." 15 minutes ago Up 15 minutes 443/tcp, 0.0.0.0:8888->80/tcp static-site-2 | |
c66fe62638aa seqvence/static-site "/bin/sh -c 'cd /u..." 2 hours ago Up 2 hours 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp static-site | |
//==>Note: Perceba os NAMES: static-site-2 AND static-site. | |
We could use CONTAINER ID or NAMES to stop the process. | |
ila@ila:~$ dk container stop 6d8d23eb31f0 | |
6d8d23eb31f0 | |
ila@ila:~$ dk container rm 6d8d23eb31f0 | |
6d8d23eb31f0 | |
ila@ila:~$ dk container stop c66fe62638aa | |
c66fe62638aa | |
ila@ila:~$ dk container rm c66fe62638aa | |
c66fe62638aa | |
ila@ila:~$ dk container ls | |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
ila@ila:~$ | |
OR | |
we could use: | |
$ docker container stop static-site | |
$ docker container rm static-site | |
Let’s use a shortcut to remove the second site: | |
$ docker container rm -f static-site-2 | |
Run docker container ls to make sure the containers are gone. | |
Now that you’ve seen how to run a webserver inside a Docker container, how do you create your own Docker image? This is the question we’ll explore in the next section. | |
2.2 Docker Images <============================================================================================================= | |
In this section, let’s dive deeper into what Docker images are. You will build your own image, use that image to run an application locally, and finally, push some of your own images to Docker Cloud. | |
Docker images are the basis of containers. In the previous example, you pulled the seqvence/static-site image from the registry and asked the Docker client to run a container based on that image. To see the list of images that are available locally on your system, run the docker image ls command. | |
ila@ila:~$ dk image ls | |
REPOSITORY TAG IMAGE ID CREATED SIZE | |
elasticsearch latest 4255fc97fa5f 7 days ago 316MB | |
nginx latest b8efb18f159b 8 days ago 107MB | |
mongo latest 6833171fe0ad 8 days ago 359MB | |
alpine latest 7328f6f8b418 5 weeks ago 3.97MB | |
hello-world latest 1815c82652c0 7 weeks ago 1.84kB | |
seqvence/static-site latest f589ccde7957 16 months ago 191MB | |
Above is a list of images that I’ve pulled from the registry and those I’ve created myself (we’ll shortly see how). You will have a different list of images on your machine. The TAG refers to a particular snapshot of the image and the ID is the corresponding unique identifier for that image. | |
For simplicity, you can think of an image akin to a git repository - images can be committed with changes and have multiple versions. When you do not provide a specific version number, the client defaults to latest. | |
For example you could pull a specific version of ubuntu image as follows: | |
docker image pull ubuntu:12.04 | |
If you do not specify the version number of the image then, as mentioned, the Docker client will default to a version named latest. | |
So for example, the docker image pull command given below will pull an image named ubuntu:latest: | |
To get a new Docker image you can either get it from a registry (such as the Docker Cloud) or create your own. There are hundreds of thousands of images available on Docker Store. You can also search for images directly from the command line using docker search. | |
An important distinction with regard to images is between base images and child images. | |
1 - Base images => are images that have no parent images, usually images with an OS like ubuntu, alpine or debian. | |
2 - Child images => are images that build on base images and add additional functionality. | |
Another key concept is the idea of official images and user images. (Both of which can be base images or child images.) | |
1 - Official images => are Docker sanctioned images. Docker, Inc. sponsors a dedicated team that is responsible for reviewing and publishing all Official Repositories content. This team works in collaboration with upstream software maintainers, security experts, and the broader Docker community. These are not prefixed by an organization or user name. In the list of images above, the python, node, alpine and nginx images are official (base) images. To find out more about them, check out the Official Images Documentation. | |
https://docs.docker.com/docker-hub/official_repos/ | |
2 - User images => are images created and shared by users like you. They build on base images and add additional functionality. Typically these are formatted as user/image-name. The user value in the image name is your Docker Cloud user or organization name. | |
2.3 Create your first image <============================================================================================ | |
Now that you have a better understanding of images, it’s time to create your own. Our goal here is to create an image that sandboxes a small Flask application. | |
The goal of this exercise is to create a Docker image which will run a Flask app. | |
We’ll do this by first pulling together the components for a random cat picture generator built with Python Flask, then dockerizing it by writing a Dockerfile. Finally, we’ll build the image, and then run it. | |
2.3.1 Create a Python Flask app that displays random cat pix <================================================================ | |
For the purposes of this workshop, we’ve created a fun little Python Flask app that displays a random cat .gif every time it is loaded - because, you know, who doesn’t like cats? | |
Start by creating a directory called flask-app where we’ll create the following files: | |
app.py | |
requirements.txt | |
templates/index.html | |
Dockerfile | |
Make sure to cd flask-app before you start creating the files, because you don’t want to start adding a whole bunch of other random files to your image. | |
You will also need a text editor. We recommend vim, which will already be installed in the terminal. However if you wanted, for example, emacs, you would install it using the Alpine package manager: | |
$ apk add --update emacs | |
app.py | |
Create the app.py with the following content: | |
from flask import Flask, render_template | |
import random | |
app = Flask(__name__) | |
# list of cat images | |
images = [ | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26388-1381844103-11.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr01/15/9/anigif_enhanced-buzz-31540-1381844535-8.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26390-1381844163-18.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-1376-1381846217-0.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3391-1381844336-26.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-29111-1381845968-0.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3409-1381844582-13.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr02/15/9/anigif_enhanced-buzz-19667-1381844937-10.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26358-1381845043-13.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-18774-1381844645-6.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-25158-1381844793-0.gif", | |
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/10/anigif_enhanced-buzz-11980-1381846269-1.gif" | |
] | |
@app.route('/') | |
def index(): | |
url = random.choice(images) | |
return render_template('index.html', url=url) | |
if __name__ == "__main__": | |
app.run(host="0.0.0.0") | |
requirements.txt | |
In order to install the Python modules required for our app, we need to create a file called requirements.txt and add the following line to that file: | |
Flask==0.10.1 | |
templates/index.html | |
Create a directory called templates and create an index.html file in that directory with the following content in it: | |
<html> | |
<head> | |
<style type="text/css"> | |
body { | |
background: black; | |
color: white; | |
} | |
div.container { | |
max-width: 500px; | |
margin: 100px auto; | |
border: 20px solid white; | |
padding: 10px; | |
text-align: center; | |
} | |
h4 { | |
text-transform: uppercase; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h4>Cat Gif of the day</h4> | |
<img src="{{url}}" /> | |
<p><small>Courtesy: <a href="http://www.buzzfeed.com/copyranter/the-best-cat-gif-post-in-the-history-of-cat-gifs">Buzzfeed</a></small></p> | |
</div> | |
</body> | |
</html> | |
2.3.2 Write a Dockerfile <====================================================================================================== | |
We want to create a Docker image with this web app. As mentioned above, all user images are based on a base image. Since our application is written in Python, we will build our own Python image based on Alpine. We’ll do that using a Dockerfile. | |
A Dockerfile is a text file that contains a list of commands that the Docker daemon calls while creating an image. The Dockerfile contains all the information that Docker needs to know to run the app — a base Docker image to run from, location of your project code, any dependencies it has, and what commands to run at start-up. It is simple way to automate the image creation process. The best part is that the commands you write in a Dockerfile are almost identical to their equivalent Linux commands. This means you don’t really have to learn new syntax to create your own Dockerfiles. | |
https://docs.docker.com/engine/reference/builder/#usage | |
1 - Create a file called Dockerfile, and add content to it as described below. | |
We’ll start by specifying our base image, using the FROM keyword: | |
FROM alpine:edge | |
2 - The next step usually is to write the commands of copying the files and installing the dependencies. But first we will install the Python pip package to the alpine linux distribution. This will not just install the pip package but any other dependencies too, which includes the python interpreter. Add the following RUN command next: | |
RUN apk add --update py2-pip | |
3 - Let’s add the files that make up the Flask Application. | |
Install all Python requirements for our app to run. This will be accomplished by adding the lines: | |
COPY requirements.txt /usr/src/app/ | |
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt | |
Copy the files you have created earlier into our image by using COPY command. | |
COPY app.py /usr/src/app/ | |
COPY templates/index.html /usr/src/app/templates/ | |
4 - Specify the port number which needs to be exposed. Since our flask app is running on 5000 that’s what we’ll expose. | |
EXPOSE 5000 | |
5 - The last step is the command for running the application which is simply - python ./app.py. Use the CMD command to do that: | |
CMD ["python", "/usr/src/app/app.py"] | |
The primary purpose of CMD is to tell the container which command it should run by default when it is started. | |
6 - Verify your Dockerfile. | |
Our Dockerfile is now ready. This is how it looks: | |
# our base image | |
FROM alpine:edge | |
# Install python and pip | |
RUN apk add --update py2-pip | |
# install Python modules needed by the Python app | |
COPY requirements.txt /usr/src/app/ | |
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt | |
# copy files required for the app to run | |
COPY app.py /usr/src/app/ | |
COPY templates/index.html /usr/src/app/templates/ | |
# tell the port number the container should expose | |
EXPOSE 5000 | |
# run the application | |
CMD ["python", "/usr/src/app/app.py"] | |
2.3.3 Build the image <========================================================================================================= | |
(Create a base image) | |
https://docs.docker.com/engine/userguide/eng-image/baseimages/#create-a-full-image-using-tar | |
Now that you have your Dockerfile, you can build your image. The docker image build command does the heavy-lifting of creating a docker image from a Dockerfile. | |
When you run the docker image build command given below, make sure to replace <YOUR_USERNAME> with your username. This username should be the same one you created when registering on Docker Cloud. If you haven’t done that yet, please go ahead and create an account. | |
The docker image build command is quite simple - it takes an optional tag name with the -t flag, and the location of the directory containing the Dockerfile - the . indicates the current directory: | |
docker image build -t <YOUR_USERNAME>/myfirstapp . | |
ila@ila:~/vhosts/flask-app$ docker image build -t igoralves1/myfirstapp . | |
Sending build context to Docker daemon 2.098MB | |
Step 1/8 : FROM alpine:edge | |
edge: Pulling from library/alpine | |
1d48052caa4a: Pull complete | |
Digest: sha256:79d50d15bd7ea48ea00cf3dd343b0e740c1afaa8e899bee475236ef338e1b53b | |
Status: Downloaded newer image for alpine:edge | |
---> 6ab1c97283af | |
Step 2/8 : RUN apk add --update py2-pip | |
---> Running in 004da1116c71 | |
fetch http://dl-cdn.alpinelinux.org/alpine/edge/main/x86_64/APKINDEX.tar.gz | |
fetch http://dl-cdn.alpinelinux.org/alpine/edge/community/x86_64/APKINDEX.tar.gz | |
(1/12) Installing libbz2 (1.0.6-r5) | |
(2/12) Installing expat (2.2.2-r0) | |
(3/12) Installing libffi (3.2.1-r3) | |
(4/12) Installing gdbm (1.13-r0) | |
(5/12) Installing ncurses-terminfo-base (6.0_p20170701-r0) | |
(6/12) Installing ncurses-terminfo (6.0_p20170701-r0) | |
(7/12) Installing ncurses-libs (6.0_p20170701-r0) | |
(8/12) Installing readline (7.0.003-r0) | |
(9/12) Installing sqlite-libs (3.20.0-r0) | |
(10/12) Installing python2 (2.7.13-r2) | |
(11/12) Installing py-setuptools (33.1.1-r1) | |
(12/12) Installing py2-pip (9.0.1-r1) | |
Executing busybox-1.27.0-r3.trigger | |
OK: 61 MiB in 23 packages | |
---> df637b41ce69 | |
Removing intermediate container 004da1116c71 | |
Step 3/8 : COPY requirements.txt /usr/src/app/ | |
---> ae1c4208705f | |
Removing intermediate container f00f4c692e02 | |
Step 4/8 : RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt | |
---> Running in e962827210eb | |
Collecting Flask==0.10.1 (from -r /usr/src/app/requirements.txt (line 1)) | |
Downloading Flask-0.10.1.tar.gz (544kB) | |
Collecting Werkzeug>=0.7 (from Flask==0.10.1->-r /usr/src/app/requirements.txt (line 1)) | |
Downloading Werkzeug-0.12.2-py2.py3-none-any.whl (312kB) | |
Collecting Jinja2>=2.4 (from Flask==0.10.1->-r /usr/src/app/requirements.txt (line 1)) | |
Downloading Jinja2-2.9.6-py2.py3-none-any.whl (340kB) | |
Collecting itsdangerous>=0.21 (from Flask==0.10.1->-r /usr/src/app/requirements.txt (line 1)) | |
Downloading itsdangerous-0.24.tar.gz (46kB) | |
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->Flask==0.10.1->-r /usr/src/app/requirements.txt (line 1)) | |
Downloading MarkupSafe-1.0.tar.gz | |
Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, Flask | |
Running setup.py install for MarkupSafe: started | |
Running setup.py install for MarkupSafe: finished with status 'done' | |
Running setup.py install for itsdangerous: started | |
Running setup.py install for itsdangerous: finished with status 'done' | |
Running setup.py install for Flask: started | |
Running setup.py install for Flask: finished with status 'done' | |
Successfully installed Flask-0.10.1 Jinja2-2.9.6 MarkupSafe-1.0 Werkzeug-0.12.2 itsdangerous-0.24 | |
---> 20d28b8fcbb1 | |
Removing intermediate container e962827210eb | |
Step 5/8 : COPY app.py /usr/src/app/ | |
---> e44cdd39b3d9 | |
Removing intermediate container f1755a027344 | |
Step 6/8 : COPY templates/index.html /usr/src/app/templates/ | |
---> 612cbf218a93 | |
Removing intermediate container 67c568058c4a | |
Step 7/8 : EXPOSE 5000 | |
---> Running in 204be43f38f2 | |
---> d66ce44c5e9b | |
Removing intermediate container 204be43f38f2 | |
Step 8/8 : CMD python /usr/src/app/app.py | |
---> Running in ce74c13bb95f | |
---> 27b27f8fcc5c | |
Removing intermediate container ce74c13bb95f | |
Successfully built 27b27f8fcc5c | |
Successfully tagged igoralves1/myfirstapp:latest | |
Now let's coffirm that the image is created. | |
ila@ila:~/vhosts/flask-app$ dk image ls | |
REPOSITORY TAG IMAGE ID CREATED SIZE | |
igoralves1/myfirstapp latest 27b27f8fcc5c 2 minutes ago 57.6MB <========= This is the image | |
alpine edge 6ab1c97283af 6 days ago 3.95MB | |
elasticsearch latest 4255fc97fa5f 7 days ago 316MB | |
nginx latest b8efb18f159b 8 days ago 107MB | |
mongo latest 6833171fe0ad 8 days ago 359MB | |
ubuntu latest 14f60031763d 2 weeks ago 120MB | |
alpine latest 7328f6f8b418 5 weeks ago 3.97MB | |
hello-world latest 1815c82652c0 7 weeks ago 1.84kB | |
seqvence/static-site latest f589ccde7957 16 months ago 191MB | |
2.3.4 Run your image <========================================================================================================== | |
The last step in this section is to run the image and see if it actually works. | |
ila@ila:~/vhosts/flask-app$ docker container run -p 8888:5000 --name myfirstapp igoralves1/myfirstapp | |
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) | |
http://172.17.0.1:8888/ | |
It Works! | |
Hit the Refresh button in the web browser to see a few more cat images. | |
OK, now that you are done with this container, stop and remove it since you won’t be using it again. If you are working in the terminal to the right, select the terminal and press Control-C. The run | |
$ docker container rm myfirstapp | |
If you are running on your local machine, you do that. Or you can open another terminal window and execute the following commands: | |
$ docker container stop myfirstapp | |
$ docker container rm myfirstapp | |
or | |
$ docker container rm -f myfirstapp | |
2.3.5 Dockerfile commands summary | |
Here’s a quick summary of the few basic commands we used in our Dockerfile. | |
FROM starts the Dockerfile. It is a requirement that the Dockerfile must start with the FROM command. Images are created in layers, which means you can use another image as the base image for your own. The FROM command defines your base layer. As arguments, it takes the name of the image. Optionally, you can add the Docker Cloud username of the maintainer and image version, in the format username/imagename:version. | |
RUN is used to build up the Image you’re creating. For each RUN command, Docker will run the command then create a new layer of the image. This way you can roll back your image to previous states easily. The syntax for a RUN instruction is to place the full text of the shell command after the RUN (e.g., RUN mkdir /user/local/foo). This will automatically run in a /bin/sh shell. You can define a different shell like this: RUN /bin/bash -c 'mkdir /user/local/foo' | |
COPY copies local files into the container. | |
CMD defines the commands that will run on the Image at start-up. Unlike a RUN, this does not create a new layer for the Image, but simply runs the command. There can only be one CMD per a Dockerfile/Image. If you need to run multiple commands, the best way to do that is to have the CMD run a script. CMD requires that you tell it where to run the command, unlike RUN. So example CMD commands would be: | |
CMD ["python", "./app.py"] | |
CMD ["/bin/bash", "echo", "Hello World"] | |
EXPOSE opens ports in your image to allow communication to the outside world when it runs in a container. | |
Note: If you want to learn more about Dockerfiles, check out Best practices for writing Dockerfiles. | |
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/ | |
What command starts a container from the command line? docker container run | |
How do you get a list of running containers? docker container ls | |
Which of the following are Dockerfile commands? RUN, CMD, COPY, FROM | |
What is the first command in every Dockerfile? FROM | |
https://www.youtube.com/watch?v=YFl2mCHdv24 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment