docker pull centos:7
Principal Middleware Architect Blog: http://blog.christianposta.com Twitter: @christianposta Email: christian@redhat.com |
Committer on Apache ActiveMQ, Apache Camel, Fabric8
Technology evangelist, recovering consultant
Spent a lot of time working with one of the largest Microservices, web-scale, unicorn companies
Frequent blogger and speaker about open-source, cloud, microservices
Intro / Prep Environments
Day 1: Docker Deep Dive
Day 2: Kubernetes Deep Dive
Day 3: Advanced Kubernetes: Concepts, Management, Middleware
Day 4: Advanced Kubernetes: CI/CD, open discussions
A company?
A format?
An API?
Linux-native functionality
Has been around ~ 10 years?
cgroups
kernel namespaces
chroot
Linux capabilities
Security (SELinux)
Built into Kernel (RHEL7/Debian/etc)
Generically isolates resource usage (CPU, memory, disk, network)
Guarantee resources to app/set of apps
Can be adjusted on the fly
Can monitor the cgroup itself to see utilization
Isolating views of the system
Can make a process think it’s the only process
Built-in way to "virtualize" a process
mnt (mount points, filesystem)
pid (processes)
net (network stack)
ipc (inter-process comms)
uts (hostname)
user (UIDs)
"root" has all capabilities
a fine-grained division of "root"'s permissions for a process
CAP_NET_ADMIN - modify routing tables, firewalling, NAT, etc
CAP_KILL - bypass any checks for sending the kill signals
CAP_SYS_ADMIN - mount, set hostname, etc
Image format vs golden image
API
Packaging
Separation of concerns (Devs/Ops)
Density, infrastructure utilization
"We’ll put it back in Ansible"
Cattle vs Pets
Don’t change it; replace it
System created fully from automation; avoid drift
Manual intervention is error prone
How does Docker help?
Docker client
Docker daemon
Images
Registry
Containers
Templates from which containers are created
Layered using union filesystems
Each change to the system is a layer
Typically created with Dockerfiles/instructions
Stored in a docker registry (public/private)
Runtime instances of a Docker Image
Copy on write file system; changes localized
"virtualized" with namespaces, cgroups, selinux, etc
Has own IP address/networking/volumes
Intended to run single process (process virtualization)
work from vagrant image
can trash and reboot it any time
locally running docker client
Source code in developer IDE
When ready, use tooling to generate docker image (or hand craft)
Run image locally (possibly with others)
Push code (or image?)
CI process kicks in
Pull Centos7 from DockerHub (http://docker.io)
docker pull centos:7
output:
ceposta@postamac(~) $ docker pull centos:7 7: Pulling from library/centos
fa5be2806d4c: Pull complete 0cd86ce0a197: Pull complete e9407f1d4b65: Pull complete c9853740aa05: Pull complete e9fa5d3a0d0e: Pull complete Digest: sha256:def5c79bc29849815dec7dddc8f75530a9115c94d5b17e0e6807f929902fab62 Status: Downloaded newer image for centos:7
List locally, installed images
docker images
output:
ceposta@postamac(~) $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE centos 7 e9fa5d3a0d0e 2 days ago 172.3 MB
Show all images, including itermmediate
docker images -a
output:
ceposta@postamac(~) $ docker images -a REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE centos 7 e9fa5d3a0d0e 2 days ago 172.3 MB <none> <none> c9853740aa05 2 days ago 172.3 MB <none> <none> e9407f1d4b65 2 days ago 172.3 MB <none> <none> 0cd86ce0a197 2 days ago 172.3 MB <none> <none> fa5be2806d4c 5 weeks ago 0 B
Let’s run a linux command inside a docker container:
docker run --rm centos:7 echo "hello world"
output:
ceposta@postamac(~) $ docker run --rm centos:7 echo "hello world" hello world
Woah, what happened? It just printed out "hello, world"? So what?
Let’s run a shell inside a docker container:
docker run -it --rm centos:7 bash
output:
[root@d7dfcc490cbe /]# _
Cool! We have a bash shell, and a minimal distro of Centos 7!
Did you see how fast that booted up?
Typing ls -l /etc/*-release
from the new bash prompt shows us we indeed have a Centos 7 distro:
[root@c2c2b8a65afe /]# ll /etc/*-release -rw-r--r-- 1 root root 38 Mar 31 2015 /etc/centos-release -rw-r--r-- 1 root root 393 Mar 31 2015 /etc/os-release lrwxrwxrwx 1 root root 14 Aug 14 21:00 /etc/redhat-release -> centos-release lrwxrwxrwx 1 root root 14 Aug 14 21:00 /etc/system-release -> centos-release
Run some other commands from within the container:
hostname -f
cat /etc/hosts
ps aux
yum -y install vim
ip a
A real linux distro right? Did you notice that ps aux
didn’t show too many processes?
Let’s do some destructive stuff:
rm -fr /usr/sbin
Wuh? you deleted all of the sacred system tools!?
Let’s delete some user tools too
rm -fr /usr/bin
output:
[root@c2c2b8a65afe /]# ls bash: /usr/bin/ls: No such file or directory
Whoops… cannot ls
or do anything useful anymore. What have we done!?
No worries! Just exit
the container and fire up a new one:
docker run -it --rm centos:7 bash
Everything is back! Phew….
Now let’s run a JVM based application like Apache Tomcat:
docker run --rm -p 8888:8080 tomcat:8.0
Since the Tomcat 8.0 docker image doesn’t exist, Docker will try to automatically pull it from the registry. Give it a moment, and you should see tomcat start successfully:
16-Oct-2015 18:30:51.541 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/manager has finished in 28 ms 16-Oct-2015 18:30:51.542 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/examples 16-Oct-2015 18:30:52.108 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/examples has finished in 566 ms 16-Oct-2015 18:30:52.117 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/ROOT 16-Oct-2015 18:30:52.161 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/ROOT has finished in 45 ms 16-Oct-2015 18:30:52.176 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"] 16-Oct-2015 18:30:52.206 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"] 16-Oct-2015 18:30:52.208 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1589 ms
Let’s explore that command for a quick sec:
docker run --rm -p 8888:8080 tomcat:8.0
--rm
tells us that we want to remove the container (delete) when it’s done running
-p 8888:8080
tells us we want to map the container’s port 8080
to the host port of 8888
So if we try to connect to http://localhost:8888
we should be able to reach our tomcat server!
Well, not quite. Why not?
Our Docker Host has been mapped properly, but we cannot reach it from our host (Windows/MacOSX) because the VM does not expose those ports.
Enable port forwarding between the VM Host (windows/Mac) and the VM Guest (Docker host):
Now navigate in a browser to http://localhost:8888
We have a running container that has tomcat in it! WooHoo! Let’s explore the tomcat container really quick. Fire up a new shell window (separate than the running tomcat docker container from previous)
docker ps
output:
ceposta@postamac(~) $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c2c059a3baab tomcat:8.0 "catalina.sh run" 36 minutes ago Up 36 minutes 0.0.0.0:8888->8080/tcp dreamy_kowalevski
Let’s log into the container to explore:
docker exec -it <container_id> bash
We should now be at the bash prompt for the tomcat container. Feel free to explore around a bit.
Now exit out of the tomcat container
exit
And switch back to the other window where we ran tomcat. Let’s CTR+C
that window and exit the docker container.
We should have no containers running:
docker ps
Nor should we have any stopped containers:
docker ps -a
This is because we used the --rm
command when we started the tomcat container, so it will automatically remove
the container.
Here are some other useful docker run
flags:
--name
give your container a unique name
-d
run your container in daemon mode (in the background)
--dns
give your container a different nameserver from the host
-it
interactive with tty (wouldn’t use this with -d
)
-e
pass in environment variables to the container
--expose
expose ports from the docker container
-P
expose all published ports on the container
-p
map a specific port from the container to the host host:container
We will look at --link
and --volume
later today.
Let’s use some of those previous run
command-line flags and start tomcat in the background:
docker run -d --name="tomcat8" -p 8888:8080 tomcat:8.0
Note, we also gave this container a name, so we can refer to it by name instead of container id:
docker logs tomcat8
output:
examples 16-Oct-2015 19:19:20.441 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/examples has finished in 526 ms 16-Oct-2015 19:19:20.447 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/ROOT 16-Oct-2015 19:19:20.507 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/ROOT has finished in 60 ms 16-Oct-2015 19:19:20.515 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"] 16-Oct-2015 19:19:20.527 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"] 16-Oct-2015 19:19:20.547 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1497 ms
Let’s use a couple of interesting docker commands with our tomcat8
container:
docker top tomcat8
I know, a little misnamed — instead of the normal linux top
container, it just displays the processes running in the
container:
PID USER COMMAND 5301 root /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
What about this one:
docker inspect tomcat8
Wow… that’s a lot of information about the container! We can also use a --format
template to pick out specific info
from that output (see https://docs.docker.com/reference/commandline/inspect/
)
docker inspect --format='{{.NetworkSettings.IPAddress}}' tomcat8
or
docker inspect --format='{{.Config.Env}}' tomcat8
output:
ceposta@postamac(~) $ docker inspect --format='{{.Config.Env}}' tomcat8 [PATH=/usr/local/tomcat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LANG=C.UTF-8 JAVA_VERSION=7u79 JAVA_DEBIAN_VERSION=7u79-2.5.6-1~deb8u1 CATALINA_HOME=/usr/local/tomcat TOMCAT_MAJOR=8 TOMCAT_VERSION=8.0.28 TOMCAT_TGZ_URL=https://www.apache.org/dist/tomcat/tomcat-8/v8.0.28/bin/apache-tomcat-8.0.28.tar.gz]
Feel free to play around with the container a little bit more. When finished, stop the container:
docker stop tomcat8
If you run docker ps
you shouldn’t see the container running any more. However, docker run -a
will show all containers
even the stopped ones. We can remove a container with:
docker rm tomcat8
Then neither docker ps
nor docker ps -a
should show the container.
Image tags
Points to a specific layer
Usually the last most layer gets changed
Can have multiple tags each pointing to diff layers; same base
don’t use latest
if you can help it
Let’s start a container and check where the images/containers live on disk:
docker run -it --rm centos:7 bash
Now in another window, let’s list the docker containers running:
docker ps
Take note of the container ID. Let’ss ssh into the VM and see where the images/containers are stored:
docker-machine ssh default
Now:
sudo su -
cd /var/lib/docker
find ./aufs/mnt -name <first few letters of container id>*
This is the location where your container lives. If you inspect that folder, you’ll see the running container’s files right there.
Each directory in that location is a layer in the image. If you matched docker images -a
you should see all of those
layers in the /var/lib/docker/aufs/mnt folder
vfs
Simple
No copy-on-write support (deep copy)
Each layer is a complete listing of the FS
Robust/portable
devicemapper
block-level copy on write
aufs
original docker backend
not supported upstream (Fedora)
not supported RHEL
regular files and aufs metadata
works on files/not blocks
Docker hub: http://docker.io
Can host public images
ie, search for fedora, or jenkins, etc
Can also host private repos (like github)
Other registries:
JFrog
Quay.io
Google Container Registry
Be careful with images on Docker hub
vulnerabilities
run as root
http://www.infoq.com/news/2015/05/Docker-Image-Vulnerabilities
Use trusted registries
Red Hat Docker registry
registry.access.redhat.com:5000
Try pulling:
docker pull registry.access.redhat.com/rhel7
Encouraged to build docker images from Dockerfile
s
FROM fabric8/java-agent-bond
MAINTAINER fabric8@googlegroups.com
ENV CLASSPATH /maven/*:/maven
RUN mkdir /maven
EXPOSE 8778 9779
ADD run.sh /fabric8/run.sh
CMD [ "/fabric8/run.sh" ]
Constructs such as the following:
FROM
ADD
COPY
USER
ENV
VOLUME
WORKDIR
CMD
ENTRYPOINT
Each step in the docker file is a new image layer! Don’t put passwords into the docker file!
FROM ubuntu:14.04
MAINTAINER fabric8.io (http://fabric8.io/)
ENV GERRIT_HOME /home/gerrit
ENV GERRIT_TMP_DIR /home/tmp
ENV GERRIT_USER gerrit
ENV GERRIT_VERSION 2.11
RUN \
sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get -y upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get install -y sudo vim-tiny git && \
DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-7-jre-headless && \
DEBIAN_FRONTEND=noninteractive apt-get install -y curl
# Add user gerrit & group like also gerrit to sudo to allow the gerrit user to issue a sudo cmd
RUN groupadd $GERRIT_USER && \
useradd -r -u 1000 -g $GERRIT_USER $GERRIT_USER
RUN mkdir ${GERRIT_HOME}
# Download Gerrit
ADD http://gerrit-releases.storage.googleapis.com/gerrit-${GERRIT_VERSION}.war ${GERRIT_HOME}/${GERRIT_WAR}
# Copy the files to bin, config & job folders
ADD ./configs ${GERRIT_HOME}/configs
# Copy the plugins
ADD ./plugins ${GERRIT_HOME}/plugins
WORKDIR ${GERRIT_HOME}
EXPOSE 8080 29418
CMD ["/home/gerrit/bin/conf-and-run-gerrit.sh"]
CMD
can be overridden at run time
docker run -it centos:7 <command_to_run>
ENTRYPOINT
fixed command, pass things in as parameters
docker run -it centos:7 <params to add>
clone the following repository:
git clone git@github.com:fabric8io/base-images.git
cd
into ./base-images/java/images/centos/openjdk8/jdk
Run the folowing command from the directory that has the Dockerfile
docker build -t local.io/docker-java:latest .
Don’t forget the .
character!
Now list the docker images:
docker images
output:
ceposta@postamac(jdk (master)) $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE local.io/docker-java latest 8d11c57aafa6 Less than a second ago 431 MB tomcat 8.0 1e41e2ebc383 2 days ago 347.7 MB centos 7 e9fa5d3a0d0e 3 days ago 172.3 MB registry.access.redhat.com/rhel7 latest 82ad5fa11820 5 weeks ago 158.3 MB registry.access.redhat.com/rhel latest 82ad5fa11820 5 weeks ago 158.3 MB
The old "python" based docker registry (before Docker 1.6 has been deprecated
New docker registry exists in "Docker Distribution" tools
Can run local / scaled out docker registries
Backed by storage
Getting started: https://docs.docker.com/registry/
Storage backends:
Implemented with a Storage API that can be extended
inmemory
local, in-memory; only expected for testing/reference
filesystem
local-storage driver
s3
Amazon S3 buckets
azure
Microsoft blob storage
rados
Ceph object storage
swift
OpenStack object storage
oss
Aliyun OSS
Let’s deploy a local registry and try it out
docker run -d -p 5000:5000 --name registry registry:2
Note, you’ll need to open ports 5000 on your VM to allow forwarding to work
output:
ceposta@postamac(temp) $ docker run -d -p 5000:5000 --name registry registry:2 Unable to find image 'registry:2' locally 2: Pulling from library/registry
f9a9f253f610: Pull complete eeb7cb91b09d: Pull complete 3c9a9d7cc6a2: Pull complete 0a17decee413: Pull complete cc85b2c38995: Pull complete 24a16bad4623: Pull complete ec4c9e01c657: Pull complete e200ab995df6: Pull complete b3b2a507517e: Pull complete 34e7db8ae1dc: Pull complete 2eafecf5086b: Pull complete Digest: sha256:802127562bcb59ac617a1296d70023258f22fc3e401fa86c866447a8c36e4278 Status: Downloaded newer image for registry:2 d89a9c4719089af289e38bcc436dff0db37aa1e82ebbe5e19ce508d87dd9cd0a
Let’s tag and push our previously created docker image to our new registry:
docker tag local.io/docker-java localhost:5000/local.io/docker-java
then push it:
docker push localhost:5000/local.io/docker-java
output:
ceposta@postamac(jdk (master)) $ docker push localhost:5000/local.io/docker-java The push refers to a repository [localhost:5000/local.io/docker-java] (len: 1) 8d11c57aafa6: Image successfully pushed f17de9438beb: Image successfully pushed b492cca03931: Image successfully pushed 9e3ba2489e43: Image successfully pushed e7c1009b53b0: Image successfully pushed 0a4fb08c5519: Image successfully pushed 78c95afc4258: Image successfully pushed 85d17ebc1200: Image successfully pushed 83af41871016: Image successfully pushed 9dbce2cf69a6: Image successfully pushed d33d90067fc7: Image successfully pushed 0aa3329df0b4: Image successfully pushed e9fa5d3a0d0e: Image already exists c9853740aa05: Image already exists e9407f1d4b65: Image already exists 0cd86ce0a197: Image successfully pushed fa5be2806d4c: Image already exists latest: digest: sha256:0cebcc42cbc25848524eff2cf4aa9d5a47e5d360c5ebfb931e6d33cfd8a38b97 size: 29837
First map the ports 8080
and 9990
from the VM to your host following the steps previusly.
We will follow the similar steps we used to deploy Tomcat and will re-use the port mappings we had earlier.
Verify your tomcat server is no longer running on 8888
and follow these steps:
docker pull arungupta/wildfly-management
docker run -d -p 9990:9990 -p 8080:8080 --name wildfly arungupta/wildfly-management
docker ps
Navigate to http://localhost:8080 to see the main page. Click "Administration Console" and login to the management console with admin/docker#admin
You can deploy applictions using the admin console… or do it the Docker way!
As discussed earlier, the "Docker way" is to package up your app as a new layer on top of the app server Docker image: Let’s look at an example Dockerfile:
# Use latest jboss/wildfly
FROM jboss/wildfly
MAINTAINER "Rafael Benevides" <benevides@redhat.com>
#Create admin user
RUN /opt/jboss/wildfly/bin/add-user.sh -u admin -p docker#admin --silent
# Add customization folder
COPY customization /opt/jboss/wildfly/customization/
USER root
# Run customization scripts as root
RUN chmod +x /opt/jboss/wildfly/customization/execute.sh
RUN /opt/jboss/wildfly/customization/execute.sh standalone standalone-ha.xml
ADD ticket-monster.war /opt/jboss/wildfly/standalone/deployments/
# Fix for Error: Could not rename /opt/jboss/wildfly/standalone/configuration/standalone_xml_history/current
RUN rm -rf /opt/jboss/wildfly/standalone/configuration/standalone_xml_history
RUN chown -R jboss:jboss /opt/jboss/wildfly/
USER jboss
# Expose the ports we're interested in
EXPOSE 8080 9990
# Set the default command to run on boot
# This will boot WildFly in the standalone mode and bind to external interface and enable HA
CMD /opt/jboss/wildfly/bin/standalone.sh -b `hostname -i` -bmanagement `hostname -i` -c standalone-ha.xml
Deploy the application:
First stop and remove the previous wildfly deployment
docker stop wildfly
docker rm wildfly
Now run the new app:
docker run -d -p 9990:9990 -p 8080:8080 --name wildfly arungupta/javaee7-hol
Navigate to http://localhost:8080/movieplex7 to see the Java EE application
We want containers to communicate with each other
Each container has an IP (veth/eth0)
Containers can expose virtual ports
Docker bridge networking can link containers without going over host network
How do we discover IP addresses, etc?
docker run --link <container_name>:alias .....
docker run --link <container_name>:alias .....
Name your containers!!!!!!!
links depend on this
alias
is what your containers will see as environment variables
example:
docker run --rm --name web2 --link db:db training/webapp env
Will create these environment variables:
DB_NAME=/web2/db DB_PORT=tcp://172.17.0.5:5432 DB_PORT_5432_TCP=tcp://172.17.0.5:5432 DB_PORT_5432_TCP_PROTO=tcp DB_PORT_5432_TCP_PORT=5432 DB_PORT_5432_TCP_ADDR=172.17.0.5
Your applications can then use environment variables to discover the dependent containers/services
docker run -t -i --rm --link db:webdb training/webapp /bin/bash
Check out /etc/hosts inside the container:
172.17.0.7 aed84ee21bde ... 172.17.0.5 webdb 6e5cdeb2d300 db
So we can just refer to containers by name: http://webdb
Injecting environment variables is a very powerful concept
Can link multiple containers together
The linking happens between one host only!!
Run a database service which will be used by a Java EE application:
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql
Note, you may need to forward the mysql
port 3306
in your VM.
Now let’s link up a Java EE application
docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7
Our app is new using the DB, but let’s log into the container and verify the environment variables/DNS was set up:
docker exec -it mywildfly bash
then type the following to list environment variables:
env
You can also take a look at the /etc/hosts
file
cat /etc/hosts`
[jboss@c924917fe4ad ~]$ cat /etc/hosts 172.17.0.30 c924917fe4ad 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.28 db ef59a1b98326 mysqldb 172.17.0.30 mywildfly.bridge 172.17.0.18 registry 172.17.0.18 registry.bridge 172.17.0.28 mysqldb 172.17.0.28 mysqldb.bridge 172.17.0.30 mywildfly
Containers are ephemeral!!!
Nothing is saved from a container if it goes away
Containers get new IP addresses
Don’t treat containers as VMs: they are not!!
But what about stateful applications?
Docker volumes to the rescue!
Persist data outside of the container
Can be mapped directly to Host locations
Can also be deployed independently of hosts/indirectly
Example:
docker run -d -P --name web -v /webapp training/webapp python app.py
Example:
docker run -d -P --name web -v /webapp training/webapp python app.py
We can also map volumes directly to Host storage locations:
Useful for known locations on Host
Can use NFS mounts
Files are visible outside of the container and are persisted
Can restart new containers up with same location
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
Example:
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
Start a container that will manage the volume
docker create -v /dbdata --name dbdata training/postgres /bin/true
Now other containers can use that container so they’re not tied directly to the volumes (mounting them, etc):
docker run -d --volumes-from dbdata --name db1 training/postgres
Let’s take an example using Jenkins. We can fire up Jenkins containers, add build jobs, etc. But if we delete the container, the jobs are lost.
docker run -d --name jenkins -p 8080:8080 jenkins
We can save the changes and jobs that jenkins creates by adding a host volume:
docker run -d --name jenkins -p 8080:8080 -v /your/home:/var/jenkins_home jenkins
Now when you run jenkins, you can stop, destroy, and re-run jenkins and your build jobs should be there.
Docker runs on a single host!
/var/lib/docker
needs to be managed!
Use only what you need in your images (avoid image bloat)
Don’t run as root
Be careful with docker images on Docker Hub (use trusted images only)
Container security… containers do not "contain"
always use image tags
Use sanity scripts to boot your process from within container
One task per container!
|