搜索镜像
docker search java
运行
docker run -it --rm ubuntu:14.04 bash
root@e7009c6ce357:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="14.04.5 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.5 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
root@e7009c6ce357:/# exit
exit
-it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
–rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 –rm 可以避免浪费空间。
ubuntu:14.04:这是指用 ubuntu:14.04 镜像为基础来启动容器。
bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash。
列出镜像
docker images
中间层
docker images -a
docker images ubuntu
docker images ubuntu:16.04
docker images -f since=mongo:3.2
docker images -f label=com.example.version=0.1
docker images -q
docker images –format “{{.ID}}: {{.Repository}}”
docker images –format “table {{.ID}}\t{{.Repository}}\t{{.Tag}}”
attach 进入容器
docker attach container-test
//推荐
docker exec -it web1 /bin/sh
Dockerfile
$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile
其内容为:
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
构建镜像
docker build -t nginx:v1 .
//运行 curl localhost:80
docker run --name web1 -d -p 80:80 nginx:v1
//8080端口访问 curl localhost:8080
docker run --name web2 -d -p 8080:80 nginx:v1
RUN 多命令
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
其他构建
docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14
压缩包构建
docker build http://server/context.tar.gz
COPY
COPY package.json /usr/src/app/
<源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则,如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
ADD
不如直接使用 RUN 指令,然后使用 wget 或者 curl 工具下载,处理权限、解压缩、然后清理无用文件更合理。
因此,这个功能其实并不实用,而且不推荐使用
CMD 容器启动命令
在运行时可以指定新的命令来替代镜像设置中的这个默认命令,
比如,ubuntu 镜像默认的 CMD 是 /bin/bash,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash。
我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release。
这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息
正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:
CMD [“nginx”, “-g”, “daemon off;”]
ENTRYPOINT
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
//-i传递给curl
docker run myip -i
场景2
这些准备工作是和容器 CMD 无关的,无论 CMD是什么,都需要事先进行一个预处理的工作。这种情况下,
可以写一个脚本,然后放入 ENTRYPOINT 中去执行,而这个脚本会将接到的参数(也就是 )作为命令,
在脚本最后执行。比如官方镜像 redis 中就是这么做的:
FROM alpine:3.4
…
RUN addgroup -S redis && adduser -S -G redis redis
…
ENTRYPOINT [“docker-entrypoint.sh”]
EXPOSE 6379
CMD [ “redis-server” ]
可以看到其中为了 redis 服务创建了 redis 用户,并在最后指定了 ENTRYPOINT 为 docker-entrypoint.sh 脚本。
#!/bin/sh
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
chown -R redis .
exec su-exec redis "$0" "$@"
fi
exec "$@"
该脚本的内容就是根据 CMD 的内容来判断,
如果是 redis-server 的话,则切换到 redis 用户身份启动服务器,
否则依旧使用 root 身份执行。比如:
$ docker run -it redis id
uid=0(root) gid=0(root) groups=0(root)
ENV
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
下列指令可以支持环境变量展开:
ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD。
VOLUME
VOLUME /data
docker run -d -v mydata:/data xxxx
EXPOSE 声明端口
WORKDIR 指定工作目录
USER 指定当前用户
HEALTHCHECK 健康检查
–interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
–timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
–retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。
案例
假设我们有个镜像是个最简单的 Web 服务,我们希望增加健康检查来判断其 Web 服务是否在正常工作,
我们可以用 curl 来帮助判断,其 Dockerfile 的 HEALTHCHECK 可以这么写:
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
这里我们设置了每 5 秒检查一次(这里为了试验所以间隔非常短,实际应该相对较长),
如果健康检查命令超过 3 秒没响应就视为失败,并且使用 curl -fs http://localhost/ || exit 1 作为健康检查命令。
使用 docker build 来构建这个镜像:
docker build -t myweb:v1 .
构建好了后,我们启动一个容器:
docker run -d --name web -p 80:80 myweb:v1
当运行该镜像后,可以通过 docker ps 看到最初的状态为 (health: starting):
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03e28eb00bd0 myweb:v1 "nginx -g 'daemon off" 3 seconds ago Up 2 seconds (health: starting) 80/tcp, 443/tcp web
在等待几秒钟后,再次 docker ps,就会看到健康状态变化为了 (healthy)。
如果健康检查连续失败超过了重试次数,状态就会变为 (unhealthy)。
为了帮助排障,健康检查命令的输出(包括 stdout 以及 stderr)都会被存储于健康状态里,可以用 docker inspect 来查看。
$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool
{
"FailingStreak": 0,
"Log": [
{
"End": "2016-11-25T14:35:37.940957051Z",
"ExitCode": 0,
"Output": "<!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n body {\n width: 35em;\n margin: 0 auto;\n font-family: Tahoma, Verdana, Arial, sans-serif;\n }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
"Start": "2016-11-25T14:35:37.780192565Z"
}
],
"Status": "healthy"
}
ONBUILD
mynode
FROM node:slim
RUN mkdir /app
WORKDIR /app
CMD [ "npm", "start" ]
other
FROM my-node
COPY ./package.json /app
RUN [ "npm", "install" ]
COPY . /app/
转变为
FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]
rmi删除本地镜像
docker rmi [选项] <镜像1> [<镜像2> ...]
docker images
docker rmi 501
docker rmi centos
docker rmi $(docker images -q -f dangling=true)
docker rmi $(docker images -q redis)
docker rmi $(docker images -q -f before=mongo:3.2)
启动
sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
sudo docker run -t -i ubuntu:14.04 /bin/bash
docker ps -a
docker start web1
后台启动
前台打印
sudo docker run ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
后台启动
sudo docker run ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
docker stop web1
docker restart web1
导出容器
sudo docker export 7691a814370e > ubuntu.tar
导入容器
cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0
$ sudo docker images
sudo docker import http://example.com/exampleimage.tgz example/imagerepo
*注:用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,
也可以使用 docker import 来导入一个容器快照到本地镜像库。
这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),
而镜像存储文件将保存完整记录,体积也要大。
此外,从容器快照文件导入时可以重新指定标签等元数据信息。
删除所有容器
docker rm $(docker ps -a -q)
私有库registry 镜像来运行。
$ sudo docker run -d -p 5000:5000 registry
指定路径
sudo docker run -d -p 5000:5000 -v /home/root/registry-conf:/registry-conf -e DOCKER_REGISTRY_CONFIG=/registry-conf/config.yml registry
docker push 172.16.1.17:5000/registry
数据卷
sudo docker run -d -P --name web -v /webapp training/webapp python app.py
sudo docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
数据库数据卷
sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres
然后,在其他容器中使用 --volumes-from 来挂载 dbdata 容器中的数据卷。
sudo docker run -d --volumes-from dbdata --name db1 training/postgres
sudo docker run -d --volumes-from dbdata --name db2 training/postgres
sudo docker run -d --name db3 --volumes-from db1 training/postgres
备份
sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
恢复
如果要恢复数据到一个容器,首先创建一个带有空数据卷的容器 dbdata2。
$ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
然后创建另一个容器,挂载 dbdata2 容器卷中的数据卷,并使用 untar 解压备份文件到挂载的容器卷中。
$ sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf
/backup/backup.tar
为了查看/验证恢复的数据,可以再启动一个容器挂载同样的容器卷来查看
$ sudo docker run --volumes-from dbdata2 busybox /bin/ls /dbdata
安装compose
curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
compose补全工具
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/dockercompose > /etc/bash_completion.d/docker-compose
目录
├── docker-compose.yml
└──eureka
├── Dockerfile
└── microservice-discovery-eureka-0.0.1-SNAPSHOT.jar
docker-compose.yml
eureka:
build: ./eureka
ports:
- "8761:8761"
expose:
- 8761
在 docker-compose.yml 所在路径执⾏:
docker-compose up
tomcat
docker run --name web2 -p 8000:8080 -d -v /root/tomcat/web1/logs:/usr/local/tomcat/logs tomcat:7
web
compose-haproxy-web
├── docker-compose.yml
├── haproxy
│ └── haproxy.cfg
└──web
├── Dockerfile
├── index.html
└── index.py
## Dockerfile
FROM python:2.7
WORKDIR /code
ADD . /code
EXPOSE 80
CMD python index.py
haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen stats
bind 0.0.0.0:70
stats enable
stats uri /
frontend balancer
bind 0.0.0.0:80
mode http
default_backend web_backends
backend web_backends
mode http
option forwardfor
balance roundrobin
server weba weba:80 check
server webb webb:80 check
server webc webc:80 check
option httpchk GET /
http-check expect status 200
docker-compose.yml
weba:
build: ./web
expose:
- 80
webb:
build: ./web
expose:
- 80
webc:
build: ./web
expose:
- 80
haproxy:
image: haproxy:latest
volumes:
- ./haproxy:/haproxy-override
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.c
fg:ro
links:
- weba
- webb
- webc
ports:
- "80:80"
- "70:70"
expose:
- "80"
- "70"
sudo docker-compose up
zk
docker run --name some-zookeeper --restart always -d zookeeper
docker run --name some-app --link some-zookeeper:zookeeper -d application-that-uses-zookeeper
docker run -it --rm --link some-zookeeper:zookeeper zookeeper zkCli.sh -server zookeeper
集群 docker-compose.xml
version: ‘2’
services:
zoo1:
image: zookeeper
restart: always
ports:
- 2181:2181
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
zoo2:
image: zookeeper
restart: always
ports:
- 2182:2181
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
zoo3:
image: zookeeper
restart: always
ports:
- 2183:2181
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
nginx集群
docker-compose.yml
version: '2'
services:
App1:
image: nginx
ports:
- "8080:80"
networks:
- "netName1"
volumes:
- /opt/conf/:/mnt
App2:
image: nginx
ports:
- "8081:80"
networks:
- "netName1"
volumes:
- /opt/conf/:/mnt
App3:
image: nginx
ports:
- "8082:80"
networks:
- "netName2"
networks:
netName1:
driver: bridge
netName2:
driver: bridge
docker-compose restart #重启所有容器
[root@docker compose]# docker-compose restart App1 #重启App1
[root@docker compose]# docker-compose stop #停止所有容器
[root@docker compose]# docker-compose stop App1 #停止App1
[root@docker compose]# docker-compose exec App1 bash
root@dd01fa7315ae:/# ping App2
django
FROM python:2.7
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
requirements.txt 文件里面写明需要安装的具体依赖包名 。
Django
psycopg2
db:
image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
docker-compose run web django-admin.py startproject django_example .
rail
FROM ruby
RUN apt-get update -qq && apt-get install -y build-essential lib
pq-dev
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
RUN bundle install
ADD . /myapp
db:
image: postgres
ports:
- "5432"
web:
build: .
command: bundle exec rackup -p 3000
volumes:
- .:/myapp
ports:
- "3000:3000"
links:
- db
docker-compose run web rails new . --force --database=postgresql --skip-bundle
wordpress
wordpress.org/latest.tar.gz | tar -xvzf -
Machine
sudo curl -L https://github.com/docker/machine/releases/download/v0.3.1-rc1/docker-machine_linux-amd64 > /usr/local/bin/docker-machine
chmod +x /usr/local/bin/docker-machine
curl -L https://github.com/docker/machine/releases/download/v0.12.1/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
chmod +x /tmp/docker-machine &&
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
docker-machine create -d generic --generic-ip-address=192.168.236.129 --generic-ssh-user=user test
swarm
docker pull swarm
docker run --rm swarm -v
sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
sudo dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap
docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise 192.168.236.128:4000 consul://192.168.236.128:8500
docker run -d swarm join --advertise=192.168.236.128:2375 consul://192.168.236.128:8500
docker run --rm swarm create
946d65606f7c2f49766e4dddac5b4365
docker run --rm swarm join --addr=192.168.0.2:2375 token://946d65606f7c2f49766e4dddac5b4365 \
time="2015-12-09T08:59:43Z" level=info msg="Registering on the discovery service every 20s..." addr="192.168.0.2:2375" \
discovery="token://946d65606f7c2f49766e4dddac5b4365"
etcd
curl -L https://github.com/coreos/etcd/releases/download/v2.3.4/etcd-v2.3.4-linux-amd64.tar.gz -o etcd-v2.3.4-linux-amd64.tar.gz
tar xzvf etcd-v2.3.4-linux-amd64.tar.gz
cd etcd-v2.3.4-linux-amd64
./etcd
docker run --net=host -d quay.io/coreos/etcd:v3.2.1 /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data
docker run --name kubernetes --net=host -d -v /var/run/docker.sock:/var/run/docker.sock \
gcr.io/google_containers/hyperkube:v0.17.0 /hyperkube kubelet \
--api_servers=http://localhost:8080 --v=2 --address=0.0.0.0 \
--enable_server --hostname_override=127.0.0.1 --config=/etc/kubernetes/manifests
docker run --name hyperkube -d --net=host --privileged gcr.io/google_containers/hyperkube:v0.17.0 /hyperkube proxy --master=http://127.0.0.1:8080 --v=2