您的位置:首页 > 运维架构 > Docker

docker详解

2017-08-17 14:33 204 查看

搜索镜像

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  docker