docker基础
docker
镜像管理
docker image pull alpin:latest
docker image ls / docker images
--filter xx=xx
danging = true/false 返回(非)悬虚镜像
before 镜像名称或id
since 镜像名称或id
label 镜像标签
--digests # 查看镜像摘要
docker image build -t img:tag
--nocache=true
--squash # 将镜像合并不分层;但生成的镜像层过大,无法共享
# 用 apt-get install no-install-recommends 减少下载量
docker image inspect # 查看镜像层
docker history # 显示镜像构建记录
docker image tag now:tag new-name:new-tag # 创建新标签
容器管理
docker container ls
docker container run -it ubuntu:latest /bin/bash
-it 交互式执行命令 并将shell连接到当前终端
Ctrl-PQ 退出容器还保持运行
docker conrainer run
-d
--name 容器名称
-p 80:80
-e # 定义环境变量
--network docker0/network-name # 指定连接的网络
-v /opt/data:/var/lib/mysql
--restart always / unless-stopped / on-failed
--flag # 将卷挂载到新建容器中
img:tag
docker exec -it 3234d5 /bin/bash # 进入到运行中的容器
docker container stop docker-id
docker container rm docker-id
docker container rm -f $(docker container ls -aq) # 删除所有容器
dockerfile
FROM image
LABEL 信息="xxx"
RUN 执行的命令 # 没执行一次创建一个新的层
COPY 终端路径 镜像路径
ADD 复制文件,同上
WORKDIR 当前工作目录
EXPOSE 记录应用使用的端口
ENV 定义环境变量
ENTRYPOINT ["镜像运行后执行的命令", "参数"] # 在shell环境下运行
CMD 执行命令 # 无shell环境,此命令会被 docker run 后的shell命令取代
例子:
FROM alpine
LABEL maintainer="nigelpoulton@hotmail.com"
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]
FROM python:3.4-alpine # 基础镜像
ADD . /code # 将app复制到镜像中
WORKDIR /code # 设置工作目录
RUN pip install -r requirements.txt # 安装依赖
CMD ["python", "app.py"] # 设置默认启动命令
onbuild:当包含onbuild指令的镜像在作为父镜像生成子镜像,在子镜像构建时父镜像onbuild指令会最先执行
FROM node:0.12.6
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ONBUILD COPY package.json /usr/src/app/
ONBUILD RUN npm install
ONBUILD COPY . /usr/src/app
CMD [ "npm", "start" ]
使用以上dockerfile生成的镜像构建子镜像时,Docker会自动将文件复制并下载依赖再复制代码
段阶段构建
FROM node:latest AS storefront
WORKDIR /usr/src/atsea/app/react-app
COPY react-app .
RUN npm install
RUN npm run build
例子:
FROM maven:latest AS appserver
WORKDIR /usr/src/atsea
COPY pom.xml .
RUN mvn -B -f pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency
\:resolve
COPY . .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package -DskipTests
FROM java:8-jdk-alpine AS production
RUN adduser -Dh /home/gordon gordon
WORKDIR /static
COPY --from=storefront /usr/src/atsea/app/react-app/build/ .
WORKDIR /app # 从其他镜像复制应用
COPY --from=appserver /usr/src/atsea/target/AtSea-0.0.1-SNAPSHOT.jar . # 从其他镜像复制
ENTRYPOINT ["java", "-jar", "/app/AtSea-0.0.1-SNAPSHOT.jar"]
CMD ["--spring.profiles.active=postgres"]
docker-compose
docker-compose up -d
down / top / stop / ps / restart
version: "3.5"
services:
web-fe:
build: . # 指定dockerfile的目录
command: python app.py # 在docker容器中执行
ports:
- target: 5000 # 将内部端口映射到外部
- published: 5000
networks:
- counter-net # 连接到制定网络
volumes:
- type: volume
source: counter-vol
target: /code # 数据持久化
- .:/lib/dir # 两种持久化方式
redis:
image: "redis:alpine"
networks:
counter-net:
networks:
counter-net:
volumes:
counter-vol:
# docker-compose [-f ./docker-compose.yml] -d
Swarm
https://docs.docker.com/engine/swarm/
docker自带的集群管理工具,使用标准docker api,可通过正常的 docker run
启动,swarm自动选择合适的主机。寻找主机和加入集群成为发现,默认使用基于令牌的方法。
swarm结构:每台主机一个Swarm代理,一台机器上运行swarm主管。有高可用模式,使用etcd、Consul、ZooKeeper使发生故障时可切换到其他主管主机。
使用端口
- 2377/tcp:用于客户端与 Swarm 进行安全通信。
- 7946/tcp 与 7946/udp:用于控制面 gossip 分发。
- 4789/udp:用于基于 VXLAN 的覆盖网络。
# 初始化节点
docker swarm init \
--advertise-addr 10.0.0.1:2377 \
--listen-addr 10.0.0.1:2377
# 列出节点
docker node ls
# 在管理节点上获得token,以 工作/管理 节点身份加入
docker swarm join-token (worker|manager)
# 工作节点加入集群
docker swarm join \
--token SWMTKN-1-0uahebax...c87tu8dx2c \
10.0.0.1:2377 \
--advertise-addr 10.0.0.4:2377 \
--listen-addr 10.0.0.4:2377
--autolock # 强制要求重启的管理节点在提供一个集群解锁码之后才有权从新接入集群
docker swarm update --autolock=true # 开启并生成解锁码
>> SWMKEY-1-5+ICW2kRxPxZrVyBDWzBkzZdSd0Yc7Cl2o4Uuf9NPU4
# 开启后再意外退出的节点加入需要解锁码
docker swarm unlock # 解锁
集群中使用了raft技术。部署奇数个管理节点,防止脑裂;不部署太多管理节点(一般3-5个最多7个),越多达成共识的时间越长。
管理swarm服务
docker service create --name web-fe \
-p 8080:8080 \
--replicas 5 \
nigelpoulton/pluralsight-docker-ci # 启动服务
docker service ls
docker service ps <service>
docker service inspect --pretty # 获取详细信息
docker service scale demo=5 # 对副本个数进行增减
docker service update # 对属性进行变更
docker service logs
docker service rm
docker stack
参考: https://zhuanlan.zhihu.com/p/182198031
在swarm集群基础上,以yml文件为配置表单实现docker容器的跨主机部署。
# 部署
docker stack deploy -c docker-stack.yml stack_name
# 查看stack
docker stack ls
# 查看stack包含的service
docker stack ps stack_name
# 获得stack包含的service id后可使用 docker service 查看
一个 docker-stack.yml 示例
version: "3" # 版本号,deploy功能是3版本特有的,所以只能写3
services: #服务,每个服务对应配置相同的一个或者多个docker容器
stack_mosquitto: # 服务名,自取
image: toke/mosquitto #创建该服务所基于的镜像
ports: # 容器内外的端口映射情况
- "1883:1883"
- "9001:9001"
networks: # 替代了命令行模式的--link选项
fiware:
aliases:
- mosquitto
volumes: # 容器内外数据传输的对应地址
- "/srv/mqtt/config:/mqtt/config:ro"
- "/srv/mqtt/log:/mqtt/log"
- "/srv/mqtt/data/:/mqtt/data/"
deploy:
replicas: 1 # replicas模式, 复制数目为1
restart_policy:
condition: on-failure
placement:
constraints: [node.role == worker] # 部署位置,只在工作节点部署
stack_mongo:
image: mongo
ports:
- "27017:27017"
networks:
fiware:
aliases:
- mongo
volumes:
- "/home/ubuntu/db:/data/db"
deploy:
replicas: 1
restart_policy:
condition: on-failure
placement:
constraints: [node.role == manager]
stack_orion:
image: fiware/orion
ports:
- "1026:1026"
networks:
fiware:
aliases:
- orion
command: -dbhost stack_mongo # 命令行模式中跟在最后的参数,此条没有固定的格式,建议参照所部署的docker镜像的说明文档来确定是否需要该项、需要写什么
deploy:
replicas: 1
restart_policy:
condition: on-failure
placement:
constraints: [node.role == manager]
stack_iotagent:
image: telefonicaiot/iotagent-ul
ports:
- "4041:4041"
- "7896:7896"
networks:
fiware:
aliases:
- iotagent
deploy:
replicas: 1
placement:
constraints: [node.role == worker]
networks: #定义部署该项目所需要的网络
fiware:
网络管理
docker 默认使用 bridge 模式
docker 默认创建名为 docker0 的Linux网桥设备,拥有一个私有网络地址和子网。所有容器被连接到该网桥并分配一个子网的IP地址,并把docker0设置为网关。创新容器时,Docker创建一对网络设备接口,一个放入容器的网络命名空间(即eth0),另一个放入宿主机的网络命名空间并连接到docker0网桥设备上。容器的流量通过NAT技术转发。
使用 docker run --network xxx
指定网络类型
- none 不使用网络
- host 容器中网络设备将与宿主机完全一致,包括docker0网桥设备。容器进程被隔离在自己的命名空间中,资源被cgroups限制,容器的网络命名空间和宿主相同。这时不能在容器内对网络进行修改。(当root用户使用--network=host --privileged=true启用host网络主机时非常危险,但适合对网络IO性能非常敏感的进程)
- bridge 单机桥接网络,只能本机上的容器相互通信
- overlay 分布式网络,swarm集群中网络
docker network ls
docker network create -d bridge localnet # 创建本地桥接网络
docker network create -d macvlan \
--subnet=10.0.0.0/24 \
--ip-range=10.0.0.0/24 \
--gateway=10.0.0.1 \
-o parent=eth0.100 \
macvlan100
docker network create -d overlay uber-net
子命令 | 说明 |
---|---|
docker network connect | 将容器连接到网络。 |
docker network create | 创建新的 Docker 网络。默认情况下,在 Windows 上会采用 NAT 驱动,在 Linux 上会采用 Bridge 驱动。可以使用 -d 参数指定驱动(网络类型)。 |
docker network disconnect | 断开容器的网络。 |
docker network inspect | 提供 Docker 网络的详细配置信息。 |
docker network ls | 用于列出运行在本地 Docker 主机上的全部网络。 |
docker network prune | 删除 Docker 主机上全部未使用的网络。 |
docker network rm | 删除 Docker 主机上指定网络。 |
卷管理
docker volume create myvol
docker volume inspect
docker volume ls
docker volume prune
docker volume rm
version: '2.0'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis network: - mynetwork
redis:
image: redis network: - mynetwork
volumes:
logvolume01: {}network: mynetwork: driver: bridge
# 可能等同于下方命令
docker build .
docker run -d -p 5000:5000 \
-v .:/code -v logvolume01 \
--link redis --name web
docker run -d --name redis redisdocker volume create logvolume01docker network create mynetwork
几个 docker-compose 配置文件的例子
# wordpress-mysql
version: '3'
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
networks:
- my-bridge
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/var/lib/mysql
networks:
- my-bridge
volumes:
mysql-data:
networks:
my-bridge:
driver: bridge
version: "3"
services:
voting-app:
build: ./voting-app/.
volumes:
- ./voting-app:/app
ports:
- "5000:80"
links:
- redis
networks:
- front-tier
- back-tier
result-app:
build: ./result-app/.
volumes:
- ./result-app:/app
ports:
- "5001:80"
links:
- db
networks:
- front-tier
- back-tier
worker:
build: ./worker
links:
- db
- redis
networks:
- back-tier
redis:
image: redis
ports: ["6379"]
networks:
- back-tier
db:
image: postgres:9.4
volumes:
- "db-data:/var/lib/postgresql/data"
networks:
- back-tier
volumes:
db-data:
networks:
front-tier:
back-tier:
docker service create --name wordpress\
-p 80:80\
-e WORDPRESS_ROOT_PASSWORD=000000\
-e WORDPRESS_DB_NAME=wordpress\
--network my-overlay\
wordpress
docker service create --name mysql \
-e MYSQL_ROOT_PASSWORD=000000\
-e MYSQL_DATABASE=wordpress\
--network my-overlay\
--mount type=volume,source=volume-demo,destination=/var/lib/mysql\
mysql