Docker详解

0. docker镜像加速器

# 编辑配置文件 /etc/docker/daemon.json
{
    "registry-mirrors": [
        "https://1nj0zren.mirror.aliyuncs.com",
        "https://docker.mirrors.ustc.edu.cn",
        "http://f1361db2.m.daocloud.io",
        "https://registry.docker-cn.com",
        阿里云
    ]
}
知识兔

1. pull环境

docker pull centos:tag-name
docker pull nginx
知识兔
  • 测试启动
docker run -ti --rm  centos:latest  bash
docker run -ti --rm -p 81:80 nginx bash
知识兔

2. yum配置

  • EPEL (Extra Packages for Enterprise Linux)
yum -y install epel-release
yum -y insatll vim
yum -y install python36
知识兔

Part1 Orientation

1. Test Docker version

# 查看当前docker版本号
~ docker --version / -v
# 输出
Docker version 18.09.2, build 6247962
知识兔
  • Run docker info (or docker version without --) to view even more details about your Docker installation
  • docker version:信息较少
~ docker info

Containers: 2
 Running: 1
 Paused: 0
 Stopped: 1
Images: 3
Server Version: 18.09.2
Storage Driver: overlay2
 Backing Filesystem: extfs
...
# 查看镜像信息
docker inspect 镜像名
知识兔

2. Recap and cheat sheet

1. 查看命令

# 查看本机所有镜像
docker image ls
docker images
# 只显示 images 的 id
docker images -q
# List Docker containers (running, all, all in quiet mode)
docker container ls
docker container ls --all
docker container ls -aq
# offical 表示是否是docker的官方镜像
docker search mysql

# 查看容器启动后的logs
options:
    -f:实时查看日志
docker logs 容器ID

# 查看容器的资源占用率
docker stats 容器id
# 实时查看日志
docker logs -f 容器id/name
知识兔

2. 删除

# 删除镜像,只要 run 过就需要先删除 对应的容器,如果tag为none则是其他镜像的依赖
docker rmi 镜像id
# 强制删除image
docker rmi -f 镜像id
# 删除容器
options:
    -f:强制删除
docker rm 容器id/别名
docker rm -f 容器id/别名
# 删除所有 stopped 的容器
docker container prune
# 删除所有容器和镜像
docker rm -f `docker ps -qa`
docker rmi -f `docker images -q`
知识兔

3. 启动

  • docker容器进程,如果没有在后台运行的话,就会立即挂掉(容器中必须有正在工作的进程)
# 启动容器
格式:docker run [选项] 镜像 [执行的命令]
    -d:表示后台启动,如果启动失败则需要与-it连用
    -it: 交互式终端
    --name:指定启动后的容器名称
    --rm:用于测试使用,退出容器后自动删除
    -v:宿主机目录:容器使用的目录,把容器目录挂载到宿主机
    -p:宿主机port:容器使用的port,把容器使用的port映射到宿主机的port
    -P:宿主机的port是随机的,自动指定端口
    
docker run -d -P redis
知识兔

4.备份

  • 注意导出的文件是压缩文件, xxx.tar.gz
# 导出镜像
docker save -o redis.tar.gz redis
docker save redis > redis.tar.gz
# 导入镜像
docker load -i redis.tar.gz
docker load < redis.tar.gz
# push镜像
docker commit 容器id          # 生成镜像  
docker tag 镜像id mycentos    # 给镜像加上tag,没有tag则添加,有怎复制一份
docker push repositoryname:tagname
知识兔

Part2 Containers

1. 进入容器

docker ps -a
# 进入后台启动过的容器
docker exec -it d1fe90d74edc /bin/bash
sudo docker attach 容器ID
知识兔
  • 删除镜像先删除container
# 删除一个image
docker rmi <image id>
# 删除所有image
docker rmi $(docker images -q)
知识兔

2. 把容器打包成镜像

# 二次修改容器并打包
# 进入纯净的容器
docker run -it centos /bin/bash
# 安装vim
yum install vim -y
# 退出容器
exit
# 提交容器文件
docker commit 容器id centos-vim
知识兔

3. Dockerfile

  • 一般使用 乌班图 (较小)
  • 作为基础镜像

3.1 创建dockerfile文件

  1. 对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令
  2. ADD存在压缩文件解压的功能,因此,仅仅添加文件到容器内,用COPY而不是ADD
  3. 添加远程文件/目录使用curl或wget
  4. ENV,环境变量,尽可能使用ENV增加可维护性
    • ENV MYSQL_VERSION 5.6,设置一个mysql常量
    • RUN yum install -y mysql-server="${MYSQL_VERSION}"
  5. 参数注释
  • 如果复制目录则需要在后面加上目录名称,只复制目录中的文件
# 创建dockerfile文件
vim DockerFile
1. 指定基础镜像
FROM 镜像名
2. 构建执行的命令
RUN yum install -y wget
RUN mkdir /mydata
3. 添加文件到 /mydata,如果是压缩包则自动解压
ADD etc.tar.gz /mydata
4. 本地文件copy到镜像中
COPY test.txt /mydata

5. 切换工作目录,启动后的目(默认根目录),需要使用绝对路径,没有则创建
WORKDIR /mydata
6.ENV设置变量
ENV name=henry
7. VOLUME,指定当前的数据卷
VOLUME ["/data"]
8. EXPOSE,指定 image 的端口,必须声明
EXPOSE 5900
9. LABEL指定标签,容器元信息,帮助信息
LABEL version="1.0"
10. 执行的命令,只执行最后一个CMD
CMD echo $HOME >> home.txt
CMD ['nginx', 'g', 'daemon off;']
知识兔
  • flask示例
    • 注意需要修改/etc/redis.conf,关闭保护模式,并更换bind 的ip
# Use an official Python runtime as a parent image
FROM python
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install -i https://pypi.douban.com/simple -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
知识兔
# 在当前目录下构建docker build  -t myimage -f 文件名 .# 执行,通过浏览器访问测试docker run -it -P myimage

3.2 创建app和requirements.txt

1. requirements.txt

FlaskRedis

2. app.py

from flask import Flaskfrom redis import Redis, RedisErrorimport osimport socket# Connect to Redisredis = Redis(host="172.16.44.142", port=6379, db=0, socket_connect_timeout=2, socket_timeout=2)app = Flask(__name__)@app.route("/")def hello():    try:        visits = redis.incr("counter")    except RedisError:        visits = "<i>cannot connect to Redis, counter disabled</i>"    html = "<h3>Hello {name}!</h3>" \           "<b>Hostname:</b> {hostname}<br/>" \           "<b>Visits:</b> {visits}"    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)if __name__ == "__main__":    app.run(host='0.0.0.0', port=80)

3. build app

  • Here's what ls should show
$ lsDokerfile    app.py     requirements.txt
  • 创建镜像,存储到本机Docker image registry
    • -t:指定tag
    • .:表示当前Dockerfile文件所在目录
docker build --tag/-t=friendlyhello .# 查看镜像$ docker images
  • tag默认是latest,完整语法
--tag=friendlyhello:v0.0.1

Note for Linux

  • Linux 用户proxy server settings
  • ENV command 指定host 和 port
# set proxy server, replace host:port with values for your serversENV http_proxy host:portENV http_proxy host:port
  • DNS settings:DNS设置不当pip不能正常使用,需要设置DNS server使 pip 正常使用,为Docker daemon设置DNS编辑 /etc/docker/daemon.json
{    'dns':['your_dns_address', '8.8.8.8']}
  • 本机的dns不可用时,使用goole的dns,保存后重启docker service
sudo service docker restart

4. Run the app

  • 运行app,mapping 主机port 4000 端口和 80 使用 -p
docker run -p 4000:80 friendlyhello
  • 使用http://0.0.0.0:80查看或curl http://localhost:4000
  • 后台运行app
docker run -d -p 4000:80 friendlyhello

5. Log in with your Docker ID

docker login# 或者docker login -u 用户名 -p 密码
  • 推送image到Docker Hub
# 添加tag标dockdocker tag image username/repository:tag# For exampledocker tag friendlyhello henrywzh/get-started:part2
  • Publish the image
docker push henry/repository:tag
  • 先在其他终端上登录:再运行app
docker run -p 4000:80 hernywzh/test:friendlyhello

Part3 Services

1. docker-compose.yml

  • 定义docker容器的参数
version: "3"services:  web:    # replace username/repo:tag with your name and image details    image: henrywzh/test:hello    deploy:      replicas: 5      resources:        limits:          cpus: "0.1"          memory: 50M      restart_policy:        condition: on-failure    ports:      - "4000:80"    networks:      - webnetnetworks:  webnet:

2. Run new load-balanced app

1. docker stack deploy命令

  • 需要执行如下命令
docker swarm init

2. 为app命名

  • A single container running in a service is called a task
  • web服务的名称为 app名称_web
docker stack deploy -c docker-compose.yml app名称(如:mytest)# 获取service IDdocker service ls# 查看所有服务with stackdocker stack services mytest# 展示服务的所有taskdocker service ps mytest_web# 展示所有容器的iddocker container ls -q

3. Scale the app

# 修改docker-compose.yml中的replicas=3参数# 重新部署即可docker stack deploy -c docker-compose.yml mytest_webdocker stack service ps mytest_web# 显示如下ID                  NAME                IMAGE                 NODE                    DESIRED STATE       CURRENT STATE            ERROR               PORTSo8fq9vr1lt04        mytest_web.1        henrywzh/test:hello   linuxkit-025000000001   Running             Running 11 minutes ago                       z5cyi8z0xrje        mytest_web.2        henrywzh/test:hello   linuxkit-025000000001   Running             Running 11 minutes ago                       cjsancy3bgpv        mytest_web.3        henrywzh/test:hello   linuxkit-025000000001   Running             Running 11 minutes ago                       k1ogibpmrnn2        mytest_web.4        henrywzh/test:hello   linuxkit-025000000001   Remove              Running 14 seconds ago                       sgddt44fe5aw        mytest_web.5        henrywzh/test:hello   linuxkit-025000000001   Remove              Running 14 seconds ago                       

4. take down the app and the swarm

1. Take the app down

docker stack rm mytest_web

2. Take down the swarm

docker swarm leave --force
计算机