Docker入门及实践
目录
原理
docker是操作系统层次的虚拟化技术,由于隔离的进程独立与宿主和其它隔离的进程,也称为容器。
docker与传统虚拟化技术的区别
简而言之,docker没有虚拟硬件,直接运行在宿主内核,因而更加轻量高效。
- 与传统虚拟机对比
基本概念
- 镜像:Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。此外,docker镜像是分层存储的,可以在原始镜像的基础上一层层的添加新的功能。
- 容器:是运行的镜像的实例。实质是一个拥有独立命令空间的进程,所以与其它进程是隔离的。另外容器的存储层也是动态创建的,随容器的消亡而消亡。一般采用绑定数据卷的方式来使数据持久化存在
- 仓库:镜像存储,分发的码头。
安装
# 卸载旧的版本
$ sudo apt-get remove docker \
docker-engine \
docker.io
# 安装依赖
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
lsb-release \
software-properties-common
# 换源加速
## 添加GPG密钥
$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo apt-key add -
# 官方源
# $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
# 添加docker 软件源
$ sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/debian \
$(lsb_release -cs) \
stable"
# 官方源
# $ sudo add-apt-repository \
# "deb [arch=amd64] https://download.docker.com/linux/debian \
# $(lsb_release -cs) \
# stable"
# 安装 docker
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io
# 启动docker
$ sudo systemctl enable docker
$ sudo systemctl start docker
# 建立docker组
$ sudo groupadd docker
# 将当前用户加入docker组
$ sudo usermod -aG docker $USER
# 测试Docker是否安装正确
sudo docker run hello-world
基本使用命令
- 获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
-
运行容器
-
列出镜像
-
删除镜像
$ docker image rm [选项] <镜像1> [<镜像2> ...]
Dockerfile编写
Dockerfile如同MakeFile一样是由一条条的指令组成,描述了最终镜像的构建过程
一个简单的例子
$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile
# Dockerfile内容
FROM nginx
RUN echo '<h1> Hello ,Docker!</h1>' > /usr/share/nginx/html/index.html
## FROM 指定基础镜像, 如果从空白镜像开始,则可以使用scratch
## RUN 执行命令,一个RUN就会新建一层,而Union FS是有层数的限制的,大概在127层,
## 对于没有必要新建一层的操作,一般直接用 && 连接命令
# 构建的命令
$ docker build -t nginx:v3 .
关于镜像构建上下文(Context)
因为docker其实是client/Server模式运行的,在执行docker build -t .的时候,docker client会将.目录下的所有文件打包发给位于服务端的Docker引擎,所以一般构建docker镜像的时候都是选择一个空目录,或者是构建项目所在的根目录。这样在DockerFile中需要进行文件操作,如COPY之类的,应相对这个当前目录(或者说根目录),以相对路径的形式来指定文件的位置,如./config.json而使用/opt/xxx或者../config.json的形式,Docker引擎是找不到对应文件的,因而会导致构建失误。
其它docker duild的用法
- 直接用Git repo进行构建:
docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world - 用给定tar压缩包构建:
docker build http://server/context.tar.gz - 从标准输入中读取DockerFile进行构建:
docker build - < Dockerfile - 从标准输入中读取上下文压缩进行构建: ` docker build - < context.tar.gz`
Dockerfile指令详解
COPY
# 格式
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
## 例子
COPY package.json /usr/src/app/
COPY --chown=55:mygroup files* /mydir/
COPY --chown=bin files* /mydir/
COPY --chown=1 files* /mydir/
COPY --chown=10:11 files* /mydir/
ADD
# 格式同COPY, 功能更强,源路径可以是URL,默认权限600,会自动解压,
# 一般用来添加初始的官方镜像,eg
FROM scratch
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
# 在其他的情况下推荐使用语义更明确的COPY
CMD
# shell 格式 : CMD <命令>
# exec 格式: CMD ["可执行文件", "参数1", "参数2" ...]
# 推荐使用exec格式, 实际shell格式的最终也会被解析成sh -c
# 如 CMD echo $HOME
CMD ["sh", "-c", "echo $HOME"]
# 另外容器即是进程,没有后台服务的概念
# eg
CMD service nginx start
# 会被解析成
CMD ["sh", "-c", "service nginx start"]
# 命令执行结束,sh也结束了,容器就会退出
# 正确的方式如下
CMD ["nginx", "-g", "daemon 0ff;"]
其他
# ENTERPOINT 入口点
# ENV 设置环境变量
# ARG 构建参数
# VOLUME 定义匿名卷
# EXPOSE 暴露端口
# WORKDIR 指定工作目录
# USER指定当前用户
# 等
使用
容器操作
# 启动
# docker run
docker run ubuntu:18.04 /bin/bash 'hello world'
docker run -it ubuntu:18.04 /bin/bash
# docker start
# 先通过docker container ls -a 查看已经终止的容器
# 再用docker start [container ID or name]使其继续运行
# 守护态运行
# docker run -d
# 可以将STDOUT从定向到logs中
# 然后通过docker container logs [container ID or NAMES]
# 就可以看到相关输出
# 终止
docker container stop [container ID or NAMES]
# 进入容器
# 使用docker exec 可以进入-d在守护态运行的容器
# 并且exit不会导致容器停止,docker attach 会
docker exec -i example-container bash
docker exec -it example-container bash
# 删除
# 删除特定的容器
docker container rm [container ID or NAMES]
# 删除所有已经终止的容器
docker container prune
数据管理
# 数据卷
## 创建一个数据卷
docker volume create my-vol
## 查看数据卷
docker volume ls
## 查看数据卷的具体信息
docker volume inspect my-vol
## 启动一个挂载数据卷的容器
docker run -d -P --name web \
--mount source=my-vol,target=/usr/share/nginx/html\
nginx:alpine
## 删除数据卷
docker colume rm my-vol
## 删除未被使用的数据卷
# 挂载主机目录
docker run -d -P \
--name web \
--mount type=bind,source=/src/webapp,