一、安装
卸载旧安装
# 非管理员用户需要加 sudo
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
安装 Docker Engine-Community
在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库。之后,您可以从仓库安装和更新 Docker。
安装所需的软件包。yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2。
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
阿里云仓库地址:
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 安装 Docker Engine-Community
安装最新版本的 Docker Engine-Community 和 containerd。
sudo yum install docker-ce docker-ce-cli containerd.io
启动docker
sudo systemctl start docker
查看docker版本
sudo docker -v
配置docker开机自启动
sudo systemctl enable docker
配置docker镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://<你的id>.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
二、拉取镜像,创建容器
MySQL
拉取镜像
# 拉取镜像
docker pull mysql:5.7
创建测试容器,查看配置及数据卷位置
创建测试容器
docker run \
-p 3306:3306 \
--name mysql57 \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
进入容器内部
docker exec -it mysql57 /bin/bash
查看配置文件所在
mysql --help | grep my.cnf
显示如下,意思是路径按优先排序,会是在以下路径里:
经过确认,配置文件在/etc/mysql/
目录下。查找数据文件位置
docker inspect mysql57
此命令可以输出指定容器的状态信息,其中包含了容器挂载情况,部分内容如下:
可以看到,当前数据卷挂载在容器内部,此时若移除容器或容器出现故障,就会导致数据丢失。绿色框表示当前mysql的数据所在所在位置/var/lib/mysql
,我们后续就可以将此目录与宿主机的指定目录挂载,做到容器与数据分离。
创建容器
在宿主机创建好对应的挂载目录:
mkdir -p /opt/docker/mysql/conf && mkdir -p /opt/docker/mysql/data && mkdir -p /opt/docker/mysql/log
创建好本地的挂载数据路径后,我们再将测试容器里 MySQL 的配置文件复制到该路径。日后需改配置,直接在挂载路径的配置文件上修改即可。
docker cp mysql57:/etc/mysql/my.cnf /opt/docker/mysql/conf
创建容器:
docker run \
-p 3306:3306 \
--name mysql57 \
-v /opt/docker/mysql/log:/var/log/mysql \
-v /opt/docker/mysql/data:/var/lib/mysql \
-v /opt/docker/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
docker run \
--name mysql57 \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=root \
--mount type=bind,src=/opt/docker/mysql/conf/my.cnf,dst=/etc/mysql/my.cnf \
--mount type=bind,src=/opt/docker/mysql/data,dst=/var/lib/mysql \
--mount type=bind,src=/opt/docker/mysql/log,dst=/var/log/mysql \
--restart=on-failure:3 \
-d mysql:5.7
- —name:为容器指定一个名字
- -p:指定端口映射,格式为:主机(宿主)端口:容器端口
- -e:username=”xxx”,设置环境变量
- —restart=on-failure:3:是指容器在未来出现异常退出(退出码非0)的情况下循环重启3次
- -mount:绑定挂载
- -d:后台运行容器,并返回容器 id
- 修改配置文件
在宿主机/opt/docker/mysql/conf
目录下,创建并修改配置文件:
# 配置文件内容如下:
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
init_connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
Redis
拉取镜像
docker pull redis:5.0.14
创建容器 ```shell
为了避免目录挂载时,将redis.conf误认为一个目录,出现异常,我们先创建出对应的目录及配置文件
mkdir -p /opt/docker/redis/conf
touch /opt/docker/redis/conf/redis.conf
运行出容器
docker run \ -p 6379:6379 \ —name redis5014 \ —mount type=bind,src=/opt/docker/redis/conf/redis.conf,dst=/etc/redis/redis.conf \ —mount type=bind,src=/opt/docker/redis/data,dst=/var/lib/redis \ -d redis:5.0.14 \ redis-server /etc/redis/redis.conf
也可以不手动创建配置文件,从官网获取。
3. 错误处理
执行上述命令后,发现容器没有启动起来哈哈!<br />使用命令`docker logs redis5014`发现,存在报错信息:<br /><br />意思是不能够打开对应的aof文件,看了一下挂载的目录,发现没有生成aof、rdb文件,可能是权限不够,没有生成成功,手动创建了两个文件并修改权限至`666`,重新启动容器,成功!
touch appendonly.aof
touch dump.rdb

chmod 666 appendonly.aof
chmod 666 dump.rdb

4. 配置远程访问
当我们使用第三方工具,远程连接redis时,发现连接一直不成功,这是由于开启redis-server后,redis-cli只能访问到127.0.0.1,因为在配置文件中固定了ip,因此需要修改redis.conf,将配置文件中的`bind 127.0.0.1`给注释掉,重启redis容器即可正常远程访问。
<a name="IYX59"></a>
# 三、常用命令
<a name="VCAvd"></a>
## 3.1 镜像命令
<a name="sVoQX"></a>
### 1. 列出本机上的镜像
```sql
docker images [OPTIONS]
docker images
Options说明:
- -a
列出本地所有的镜像(包含中间映像层)。
docker images -a
- -q
只显示镜像ID。
docker images -q
—digests
docker images --digests
—no-trunc
docker images --digests --no-trunc
2. 从DockerHub上搜索镜像信息
```sql docker search [OPTIONS] tomcat
docker search tomcat

**Options说明:**
1. -f
列出收藏数不小于指定值的镜像。
```sql
docker search -f stars=30 tomcat
- —no-trunc
显示完整的镜像描述。
docker search -f stars=30 --no-trunc tomcat
3. 拉取镜像(下载)
注意:不携带版本的话,默认为latest
docker pull 镜像名称
docker pull 镜像名称:Tag
docker pull nginx
4. 删除镜像
- 删除单个镜像 ```sql docker rmi 某个镜像名字id
docker rmi hello-world:latest
当镜像已经创建出容器,则删除会失败:<br /><br />需要使用强制删除:
```sql
docker rmi -f 镜像名称
docker rmi -f hello-world:latest
- 删除多个镜像 ```sql docker rmi -f 镜像1名称及标签 镜像2名称及标签
docker rmi -f nginx:latest hello-world:latest

3. 删除全部镜像(慎用)
```sql
docker rmi -f ${docker images -qa}
3.2 容器命令
1. 新建并启动容器
docker run [OPTIONS] 镜像名称及标签
docker run -it centos:7
创建了一个centos容器,并进入容器内:
可以执行linux命令:
Options说明:
有些是一个-
,有些是两个-
。
- -i
以交互模式运行容器,通常与-t
同时使用。
- -t
为容器重新分配一个伪输入终端,通常与-i
同时使用。
- —name
为容器指定一个名称。
--name="容器新名字"
- -d
后台运行容器,并返回容器id,也即启动守护式容器。
- -P
随机端口映射。
- -p
指定端口映射,有以下四种方式:
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
(最常用)containerPort
2. 列出当前所有正在运行中的容器
docker ps [OPTIONS]
Options说明:
- -a
列出当前所有正在运行的容器 + 历史上运行过的容器。
- -l
显示最近创建的容器。
- -n
显示最近n个创建的容器。
- -q
静默模式,只显示容器编号。
- —no-trunc
不截断输出
3. 退出容器
容器停止退出
exit
退出后:
容器不停止退出
ctrl + P + Q
4. 启动容器
docker start 容器id或者容器名称
5. 停止容器
docker stop 容器名称或容器id
6. 重启容器
docker restart 容器名称或容器id
7. 强制停止容器
docker kill 容器名称或容器id
8. 删除已停止的容器
可加-f
删除未停止的容器。
docker rm 容器id
# 一次性删除多个容器
docker rm -f ${docker ps -a -q}
docker ps -a -q | xargs docker rm
9. 新建并启动守护式容器
docker run -d 镜像名
docker run -d centos
10. 查看容器日志
docker logs -f -t --tail 10 容器id
Options说明:
- -t
加入时间戳
- -f
跟随最新的日志打印
- —tail
显示最后多少条
--tail 数字
11. 查看容器内运行的进程
docker top 容器名称/容器id
docker top mycentos1117
12. 查看容器内部细节
docker inspect 容器名称或容器id
docker inspect mycentos1117
13. 进入正在运行的容器并以命令行交互
# docker exec -it 容器名称或容器id /bin/bash
docker exec -it mycentos1117 /bin/bash
# docker attach 容器名称或容器id
docker attach mycentos1117
exec 和 attach 区别:
- attach:直接进入容器启动命令的中断,不会启动新的进程(容器停止时,无法进入)
- exec:是在容器中打开新的终端,并且可以启动新的进程
如图:
14. 从容器内拷贝文件到主机上
# docker cp 容器名称或容器id:容器内路径 宿主机路径
docker cp heuristic_keller:/tmp/yum.log /root
源地址:
目标位置:
15. 帮助命令
docker version
docker info
docker --help
四、Docker镜像
4.1 是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
Union FS(联合文件系统): Union文件系统( Union FS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。 Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看釗一个文件系,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 Union FS boots( boot file system)主要包含 bootloader和kene, bootloader主要是引导加载 kernel, Linux刚启动时会加毂 boots文件系统,在Docker镜像的最底层是 boots。这一层与我们典型的 Linux/Unⅸx系统是一样的,包含bot加载器和内核。
当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 boots转交给内核,此时系统也会卸载 boots rootfs( (root file system),在 boots之上·包含的就是典型 Linux系统中的/cev,/proc,/bin,/etc等标准目录和文件。
rootfs就是各种不同的操作系统发行版,比如 Ubuntu,censtos等等。
4.2 特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,容器层之下的都叫做“镜像层”。
4.3 Docker Commit操作
可以通过docker commit
操作提交容器副本使之成为一个新的镜像。
docker commit -m="提交的描述信息" -a="作者" 容器id或容器名称 要创建的目标镜像名:[标签名]
1. 从Hub上下载Tomcat镜像到本地并成功运行
docker pull tomcat:8.0
docker run -it -p 8888:8080 tomcat:8.0
Options说明:
- -p:主机端口:docker容器端口
- -P:随机分配端口
- -i:交互
- -t:终端
2. 故意删除上一步镜像生产Tomcat容器的文档
3. 提交此容器,形成新镜像
docker commit -a="ljl" -m="tomcat without docs" boring_hofstadter ljl/mytomcat8:1.1
4. 启动新镜像作对比
启动后,可以看到欢迎页,但是点开相关链接,页面404.
五、容器数据卷
5.1 是什么
卷就是目录或文件,存在于一个或多个容器中,由 docker挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System提供一些用于持续存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此 Docker不会在容器删除时删除其挂载的数据卷。
5.2 特点
- 数据卷可在容器之间共享或重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
5.3 数据卷操作
1. 直接命令添加
命令
docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
查看数据卷是否挂在成功
使用docker inspect
命令,查看容器详情。
docker inspect infallible_borg
可以看到数据卷挂载情况:
- 容器和宿主机之间数据共享
宿主机在挂载卷中创建文件:
容器内可以同步看到:
同样,在容器内创建文件,宿主机也同步可以看到:
- 容器停止退出后,主机修改后数据是否同步
同样是可以同步的。
docker run -it -v /test1:/test2:ro centos
**绑定情况:**<br /><br />
创建了带权限的数据卷挂载,可以看到,宿主机可以在挂载目录创建文件,容器可以看到相关的更新,但容器创建文件时失败:<br />
<a name="uKzv9"></a>
### 2. DockerFile添加
1. 根目录下新建mydocker文件夹并进入
1. 可在Dockerfile中使用`VOLUME`指令来给镜像添加一个或多个数据卷
说明:
- 出于可移植和分享的考虑,用`-v 主机目录:容器目录`这种方法不能够直接在 Dockerfile中实现。
- 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿机上都存在这样的特定目录。
创建并编辑`Dockerfile`:
volume test
FROM centos:7 VOLUME [“/dataVolumeContainer1”,”/dataVolumeContainer2”] CMD echo “finished,———success” CMD /bin/bash
上述内容相当于:
```shell
docker run -it -v /host1:/dataVolumeContainer1 -v /host2:/dataVolumeContainer2 centos /bin/bash
若没有指定宿主机挂载目录,会存在默认的挂载目录生成路径,通常为/var/lib/docker/volumes
。
docker build -f /mydocker/Dockerfile -t ljl/centos .
<br />
4. run出容器
```shell
docker run -it ljl/centos /bin/bash
通过docker inspect
命令,查看容器详情,可以看到数据卷的情况:
自动在宿主机上生成了挂载目录。
注意:Docker挂载主机目录 Docker访问出现 cannot open directory: Permission denied
解决办法:在挂载目录后多加一个--privileged=true
参数即可。
即:
-v 宿主机目录:容器目录 --privileged=true
3. volumes-from操作
在某一容器基础上,创建新的容器并做数据卷挂载操作。可以使用--volume-from
命令做容器间传递共享操作。
- 首先,在指定容器的某一目录创建一个文件
- 在上述容器的基础上,使用相同镜像运行出新的容器test02
使用如下命令操作:
# docker run -it --name 容器名称 --volumes-from 基础容器名称 镜像名
docker run -it --name test02 --volumes-from compassionate_banach ljl/centos
可以看到,新容器中,也存在基础容器中创建的文件:
在创建的容器中的同目录创建文件:
基于上步运行的容器,再次生成新的同镜像容器test03
docker run -it --name test03 --volumes-from test02 ljl/centos
可以看到,同目录中同样有容器1和容器2所创建的文件:
我们在此目录中新创建一个文件:回到容器1中,观察同目录下内容 ```java docker exec -it compassionate_banach /bin/bash
cd dataVolumeContainer1
ll
可以看到,容器1中也可以看到后续容器创建的文件:<br />
5. 删除容器1,观察后续容器内状况
可以看到,虽然删除了容器1,后续的容器内部依然可以访问到之前的所有数据:<br />
6. 创建容器test04,删除中间容器test03,测试关联状况
```java
docker run -it --name test4 --volumes-from test03 ljl/centos
容器如下:
我们先删除容器test03:
在容器test04中创建新文件:
进入容器test02中,查看文件状况,可以看到,新创建的文件依然可以在test02中看到:
对应宿主机挂载目录:
移除所有关联容器,对应挂载目录数据依然存在,但无法再依靠容器间共享来关联:
可知,使用--volume-from
命令做容器间传递共享操作,只要关联的容器没有完全删除,数据卷的生命周期可以一直持续下去。当所有关联的容器全部移除,容器间共享关系消失,但对应的挂载目录依然存在,数据依然保存在宿主机上。
六、Dockerfile
6.1 是什么
Docker是用来构建 Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建的三个步骤:
- 编写Dockerfile文件
- docker build
- docker run
6.2 Dockerfile构建过程解析
6.2.1 Dockerfile内容基础
6.2.2 Docker执行Dockerfile的大致流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似 docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新容器
- 执行 dockerfile中的下一条指令直到所有指令都执行完成
从应用软件的角度来看, Dockerfile、 Docker镜像与 Docker容器分别代表软件的三个不同阶段:
- Dockerfile是软件的原材料
- Docker镜像是软件的交付品
- Docker容器则可以认为是软件的运行态
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当 Docker体系的基石。
6.3 Dockerfile体系结构(保留字指令)
- FROM
基础镜像,当前新镜像是基于哪个镜像的。
- MAINTAINER
镜像维护者的姓名和邮箱地址。
- RUN
容器构建时需要运行的命令。
- EXPOSE
当前容器对外暴露出的端口。
- WORKDIR
指定在创建容器后,终端默认登录进来的工作目录,一个落脚点。
- ENV
用来在构建镜像过程中设置环境变量。
环境变量比如: ENV MY_PATH /usr/mytest
可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样。
也可以在其它指令中直接使用这些环境变量,比如: WORKDIR $MY_PATH
- ADD
将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包。
- COPY
类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置。
COPY src dest
COPY ["src","dest"]
- VOLUME
容器数据卷,用于数据保存和持久化工作。
- CMD
指定一个容器启动时要运行的命令。Dockerfile中可以有多个CMD命令,但只有最后一个生效,CMD
会被 docker run
之后的参数替换。
CMD 容器启动命令:CMD
指令的格式和 RUN
相似,也是两种格式:
shell
格式:CMD <命令>
exec
格式:CMD ["可执行文件","參数1","参数2"...]
- 参数列表格式:
CMD ["参数1","参数2"....]
。在指定了ENTRYPOINT
指令后,用CMD
指定具体的参数。- ENTRYPOINT
指定一个容器启动时要运行的命令。ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数。
- ONBUILD
当构建一个被继承的Dockerfile时运行命令。父镜像在被子继承后,父镜像的onbuild
被触发。
6.4 案例
6.4.1 Base镜像(scratch)
Docker Hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的。
6.4.2 自定义镜像mycentos
1. 编写
- Hub默认CentOS镜像什么情况
- 准备编写Dockerfile文件
创建dockerfile文件。
vim Dockerfile
- myCentOS的Dockerfile内容 ```shell FROM centos MAINTAINER zzyyzzyy167@126.com
ENV MYPATH /usr/local WORKDIR $MYPATH
RUN yum -y install vim RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH CMD echo “success—————ok” CMD /bin/bash
<a name="oITob"></a>
#### 2. 构建
```shell
# docker build命令最后有一个 . ,代表当前路径,可根据文件所在位置变化
docker build -t 新镜像名字:TAG .
# 在Dockerfile所在目录执行如下命令
[root@test01 mydocker]# docker build -f /mydocker/Dockerfile2 -t mycentos:1.3 .
4. 运行
docker run -it 新镜像名称:TAG
运行容器,可以看到入口目录已不再是默认的/
:
使用vim
命令也可以正常执行了:
使用ifconfig
命令也可以正常执行:
5. 列出镜像的变更历史
docker history 镜像id
docker history 镜像名称:TAG
6.4.3 CMD/ENTRYPOINT命令案例
1. CMD
对于CMD
:
Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run
之后的参数替换。
默认的Tomcat的Dockerfile中,最后的CMD命令为:
在我们运行此Tomcat镜像时,会直接启动Tomcat服务:
当我们使用如下命令运行容器,类似于在默认的CMD命令后面追加了一条CMD ["ls","-l"]
,这时会覆盖掉上一句启动Tomcat服务的命令:
docker run -it -p 7777:8080 tomcat ls -l
这时,运行容器后,只会打印出Tomcat所在目录下的内容:<br />
2. ENTRYPOINT
对于ENTRYPOINT
:
docker run之后的参数会被当做参数传递给ENTRYPOINT,之后形成新的命令组合。
2.1 制作CMD版可以查询IP信息的容器
注意:此案例已不可用!
- 编写Dockerfile文件
FROM centos
RUN yum install -y curl
CMD ["curl", "-s", "http://ip.cn"]
curl
命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。如果系统没有curl,可以使用yum install curl
安装,也可以下载安装。curl
是将下载文件输出到stdout
。
使用命令:curl [http://www.baidu.com](http://www.baidu.com)
执行后,www.baidu.com的html就会显示在屏幕上了。
这是最简单的使用方法。用这个命令获得了http://curl.haxx.se指向的页面,同样,如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将只显示文件头部,即HTML文档的header。要全部显示,请加参数 -i。
- 构建
使用如下命令运行:
docker build -f Dockerfile3 -t myip .
可以查看镜像构建情况:
- 运行
使用如下命令运行容器:
docker run -it myip
2.2 制作ENTRYPOINT版查询IP的容器
- 编写Dockerfile文件
FROM centos
RUN yum install -y curl
ENTRYPOINT ["curl", "-s", "http://ip.cn"]