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:7output:
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 imagesoutput:
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 -aoutput:
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 bashoutput:
[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 aA 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/sbinWuh? you deleted all of the sacred system tools!?
Let’s delete some user tools too
rm -fr /usr/binoutput:
[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 bashEverything is back! Phew….
Now let’s run a JVM based application like Apache Tomcat:
docker run --rm -p 8888:8080 tomcat:8.0Since 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 psoutput:
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> bashWe 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 psNor should we have any stopped containers:
docker ps -aThis 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.0Note, we also gave this container a name, so we can refer to it by name instead of container id:
docker logs tomcat8output:
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 tomcat8I 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 tomcat8Wow… 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}}' tomcat8or
docker inspect --format='{{.Config.Env}}' tomcat8output:
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 tomcat8If 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 tomcat8Then 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 bashNow in another window, let’s list the docker containers running:
docker psTake note of the container ID. Let’ss ssh into the VM and see where the images/containers are stored:
docker-machine ssh defaultNow:
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/rhel7Encouraged 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 imagesoutput:
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:2Note, 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-javathen push it:
docker push localhost:5000/local.io/docker-javaoutput:
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.xmlDeploy the application:
First stop and remove the previous wildfly deployment
docker stop wildfly
docker rm wildflyNow run the new app:
docker run -d -p 9990:9990 -p 8080:8080 --name wildfly arungupta/javaee7-holNavigate 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 envWill 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/bashCheck 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 mysqlNote, 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-javaee7Our 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 bashthen type the following to list environment variables:
envYou 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.pyExample:
docker run -d -P --name web -v /webapp training/webapp python app.pyWe 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.pyExample:
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.pyStart a container that will manage the volume
docker create -v /dbdata --name dbdata training/postgres /bin/trueNow 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/postgresLet’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 jenkinsWe 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 jenkinsNow 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!
|