docker的使用和踩坑
一、docker简介
1、什么是docker
docker: Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code, you can significantly reduce the delay between writing code and running it in production. (Docker是一个用于开发、交付和运行应用程序的开放平台。Docker使您能够将应用程序与基础设施分开,以便您可以快速交付软件。借助Docker,您可以以管理应用程序的方式管理基础设施。通过利用Docker的交付、测试和部署代码方法,您可以显着减少编写代码和在生产中运行代码之间的延迟。)Docker 是一个应用打包、分发、部署的工具,你也可以把它理解为一个
轻量的虚拟机
,它只虚拟你软件需要的运行环境,多余的一点都不要,而普通虚拟机则是一个完整而庞大的系统,包含各种不管你要不要的软件。
2、docker的打包、分发和部署
- 打包:就是把你软件运行所需的依赖、第三方库、软件打包到一起,变成一个安装包
- 分发:你可以把你打包好的“安装包”上传到一个镜像仓库,其他人可以非常方便的获取和安装
- 部署:拿着“安装包”就可以一个命令运行起来你的应用,自动模拟出一摸一样的运行环境,不管是在 Windows/Mac/Linux。
3、docker四大要素
3.1、image:镜像
镜像:容器的引用模版。可以理解为软件安装包,可以方便的进行传播和安装。容器映像是一个标准化的包,其中包含运行容器所需的所有文件、二进制文件、库和配置。镜像:即是打包好的运行环境。镜像基础是联合文件系统,由一层一层的文件系统组成。docker镜像是分层的,每一次都可复用。
docker的虚悬镜像:仓库名、标签名都是none的镜像。 docker构建的时候,可能会出现虚悬镜像
- 查看虚悬镜像: docker image ls -f dangling=true
- 删除所有虚悬镜像:docker image prune
3.2、container: 容器,解决了版本冲突
容器:镜像的实例。软件安装后的状态,每个软件运行环境都是独立的、隔离的,称之为容器。
- Self-contained. Each container has everything it needs to function with no reliance on any pre-installed dependencies on the host machine.(自包含的。每个容器都拥有运行所需的一切,而不依赖于主机上预安装的依赖项。)
- Isolated. Since containers are run in isolation, they have minimal influence on the host and other containers, increasing the security of your applications.(孤立。由于容器是隔离运行的,因此它们对主机和其他容器的影响最小,从而提高了应用程序的安全性。)
- Independent. Each container is independently managed. Deleting one container won’t affect any others.(独立的。每个容器都是独立管理的。删除一个容器不会影响其他容器。)
- Portable. Containers can run anywhere! The container that runs on your development machine will work the same way in a data center or anywhere in the cloud!(便携。容器可以在任何地方运行!在您的开发机器上运行的容器将以相同的方式在数据中心或云中的任何地方工作!)
3.3、repository:仓库
仓库:存储image的。 注册表registry > 存储库repository > 映像image
- registry : 注册表
映像注册表(Registry)是存储和共享容器映像的集中位置。它可以是公共的,也可以是私人的。Docker Hub是一个任何人都可以使用的公共注册表,也是默认的注册表。您甚至可以在本地系统或组织内部运行您的私有注册表。例如Harbor
- registry vs. repository (注册表与存储库)
3.4、docker-compose
docker-compose 。容器的一个最佳实践是,每个容器只做一件事,并且把它做好。虽然这条规则也有例外,但要避免让一个容器做多个事情。您可以使用多个docker run命令来启动多个容器。但是,您很快就会意识到您需要管理网络、将容器连接到这些网络所需的所有标志等等。当你完成后,清理就有点复杂了。使用Docker Compose,你可以在一个
单一的YAML文件中定义所有的容器及其配置
。如果将该文件包含在代码存储库中,任何克隆您的存储库的人都可以使用一个命令启动并运行。
二、docker安装
1、ubuntu
1.1、Prerequisites(安装的先决条件):
- Firewall limitations(防火墙限制)
- OS requirements(操作系统要求,即是ubuntu版本限制)
1.2、命令行输入docker version
1.3、依次执行:
snap install docker
apt install podman-docker
apt install docker.io
1.4、测试是否安装成功
1.5、官网提供的安装方式
官网提供的基于ubuntu操作系统的安装方式可自行测试。Install using the apt repository
三、docker加速镜像配置
1、hello world
docker run hello-world: 现在时本地启动hello-world镜像,此时本地没有hello-world镜像,则会去docker的仓库run,此时就会访问外网,可能会出现timeout。
2、设置docker仓库镜像
docker仓库镜像的设置可参考阿里云,也可参考dockerpull
2.1、创建并修改文件 /etc/docker/daemon.json
cd /etc/docker # 默认是没有daemon.json这个文件的
# 创建空文件
touch /etc/docker/daemon.json
# 创建一个非空文件
nano /etc/docker/daemon.json
# 文件输入
{
"registry-mirrors": [
"https://dockerpull.cn" # 这个只是docker pull的镜像
]
}
2.1、加载 /etc/docker/daemon.json配置
systemctl daemon-reload #重载systemd管理守护进程配置文件
systemctl restart docker #重启 Docker 服务
3、再次run hello-world
出现
Hello from Docker!
,则说明,docker镜像配置成功
四、docker常用命令
1、帮助启动类命令
- 启动docker:systemctl start docker
- 停止docker:systemctl stop docker
- 重启docker:systemctl restart docker
- 查看docker状态:systemctl status docker
- 开机自启动:systemctl enable docker
- 查看docker概要信息:docker info
- 查看docker总体帮助文档: docker --help
- 查看docker命令帮助文档:docker 具体命令 --help
2、镜像命令
- 查看镜像列表: docker images
- 查看前n个可安装的镜像,n默认是25:docker search --limit n 某个镜像的名字【需要设置镜像】
- 下载最新版本镜像:docker pull 某个镜像的名字
- 下载具体版本镜像:docker pull 某个镜像的名字:版本号
- 查看镜像/容器/数据卷volume所占空间: docker system df
- 删除指定 id 的镜像: docker rmi image-id
- 强制删除指定 id 的镜像: docker rmi -f image-id
3、容器命令
- 新建+启动容器:docker run [OPTIONS] 镜像名 [COMMAND] [ARG…]
- OPTIONS:
- 为容器制定名称: --name=容器新名字
- 启动守护式容器(容器服务后台运行):-d
- 启动交互式容器(启动后,返回一个操作容器的终端): -it
- 指定端口映射(云服务和docker服务端口的映射): -p
- OPTIONS:
- 前台交互式容器,如:docker run -it centos /bin/bash。
- 退出容器终端的方式
- exit: 容器停止
- ctrl+p+q: 容器不停止
- 退出容器终端的方式
- 后台守护式容器,如: docker run -d redis
- 注意:
- docker容器后台运行,就必须有一个前台进程,否则会默认被立即杀死刚run的后台进程
- 注意:
- docker ps 查看当前运行中的容器
- docker ps -a 查看所有的容器
- 重新进入激活状态的容器/进入容器内部:docker exec [OPTIONS] 容器id [COMMAND] [ARG…],如docker exec -it 容器id /bin/bash。两种进入容器内部的方式对比:
- docker exec -it 容器ID bashShell:是在容器中打开新的终端,并且可以启动新的进程,用exit退出,不会导致容器的停止。【推荐使用,exec退出容器终端,不会导致容器的停止】
- docker attach 容器ID:直接进入容器启动命令的终端,不会启动新的进程,用exit退出,会导致容器的停止。
- docker logs 容器id: 查看容器日志
- docker top 容器id; 查看容器内运行的进程
- docker inspect 容器id: 查看容器内部细节
- docker可以理解为简易版虚拟机
- 则,容器可以理解为简易版linux内核服务,即一个容器是简易版ubuntu
- docker rm container-id 删除已经停止的、指定 id 的容器
- docker stop/start container-id 停止/启动指定 id 的容器
- docker cp 容器id:容器内部路径 主机路径: 将容器里面的内容拷贝到容器外部的主机
- docker export 容器id > 文件名.tar: 将整个容器导出到外部主机,默认导出到当前目录
- cat 文件名.tar | docker import - 镜像用户(也叫镜像包名)/镜像名:镜像版本号 : 将外部容器导入到docker
五、本地镜像发布
1、提交新镜像
提交容器副本,使之成为新镜像:docker commit -m=“提交的描述信息” -a=“作者” 容器id 要创建的目标镜像名:[版本号], 例如:
docker commit -m="加了一个zhw目录到centos镜像" -a="zhw" 248efac098d3 zhw/mycentos:1.3
【此时docker images 可查看到仓库名为zhw/mycentos的镜像】
2、镜像发布到阿里云
2.1、创建命名空间
2.2、在已创建的命名空间下,新建镜像仓库
2.3、使用命令登陆阿里云
2.4、推送镜像到阿里云仓库
3、镜像发布到私有库
3.1、搭建本地私服
# pull 搭建私服的镜像
docker pull registry
# run 私服
docker run -d -p 5000:5000 -v /zhw/myregistry/:/tmp/registry --privileged=true registry
3.2、将新镜像修改符合私服的tag
docker tag zhw/mycentos:1.3 172.16.233.129:5000/zhw/mycentos:1.3
3.3、解决docker私服库默认不支持http协议推送的限制
# daemon.json 添加如下配置
"insecure-registries": ["172.16.233.129:5000"]
# 更高配置后,重启docker
systemctl daemon-reload #重载systemd管理守护进程配置文件
systemctl restart docker #重启 Docker 服务
# 重启docker后,重跑私服
docker run -d -p 5000:5000 -v /zhw/myregistry/:/tmp/registry --privileged=true registry
3.4、将本地镜像推送到私服库
3.5、查看本地私服镜像
curl -XGET http://172.16.233.129:5000/v2/_catalog
3.6、从本地私服拉取镜像
docker pull 172.16.233.129:5000/zhw/mycentos:1.3
六、docker容器数据卷volume
容器卷的命令记得加上: --privileged=true (开启挂载目录权限)
1、什么是容器数据卷
将容器里的内容备份+持久化到宿主机上。数据卷就是目录或者文件,存在于一个活多个容器中,由dokcer挂载到容器,但不属于联合文件系统。卷的设计目的就是数据持久化,完全独立于容器的生存周期,因此docker不会在容器删除时,删除其挂在的数据卷。
2、容器数据卷的特点:
- 数据卷可在容器之间共享或复用数据
- 容器内容的更改会实时的更新到数据卷中;
- 主机数据卷中的更改也可以直接实时生效到容器中;【不需要定时备份,且不管容器有没有停止】
- 数据卷中的更改不会包含在镜像的更新中;
- 数据卷的生命周期一致持续到没有容器使用它为止
2、运行一个带有数据卷存储功能的容器
docker run -it --privileged=true -v /宿主及绝对路径目录:容器内目录 镜像名
3、查看数据卷是否挂载成功
docker inspect 容器id
4、容器卷的读写规则
- 默认,可读可写rw,即是:docker run -it --privileged=true -v /宿主及绝对路径目录:容器内目录:rw 镜像名
- 容器实例里的内容只能读,不能写,即是:docker run -it --privileged=true -v /宿主及绝对路径目录:容器内目录:ro 镜像 【此时只能在数据卷中写入】
5、容器卷之间的继承
实现了多个容器、卷之间的数据共享。继承之后是独立的,互不影响的。不会因为父容器的停止有所影响。容器重启后,会共享最新的数据。
docker run [options] --privileged=true --volumes-from 需要继承的容器id/name [commonds] 镜像名
七、docker上安装常用软件
1、docker安装软件通用步骤
- 搜索镜像
- 拉取镜像
- 查看镜像
- 启动镜像
- 停止容器
- 移除容器
2、安装tomcat
# 1
docker pull tomcat
# 2
docker images tomcat
# 3. 创建tomcat容器实例
docker run -d -p 8080:8080 --name tomcatalias tomcat
# 4. 解决新版tomcat,8080访问404问题
cd /usr/local/tomcat
ls -l
rm -f webapps # 空的webapps
mv webapps.dist webapps # webapps.dist有内容的
# ===============
# 新版tomcat可能由以上的404问题,所以推荐安装如下版本
# 没有pull,直接run,会在内部pull的
# 这个版本不需要额外修改
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8
3、安装mysql
# 1.
docker pull mysql:8.4.3
# 2. 查看你linux本身有没有mysql
ps -ef|grep mysql
# 3.
# -e 环境设置
docker run -d -p 3306:3306 --privileged=true -v /data/docker/mysql/log:/var/log/mysql -v /data/docker/mysql/data:/var/lib/mysql -v /data/docker/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name=mysql-server mysql:8.4.3
# 4、进入容器实例
docker exec -it 容器id /bin/bash
# 5、查看mysql是否安装成功
mysql uroot -p123456
# 6、docker安装mysql 需要修正字符集编码,否则插入中文会乱码
# 7、查看存储卷对应的宿主存储位置
docker volume inspect vol_name
3.1、更改mysql容器的编码方式为utf-8
// 在宿主中编写配置文件
$ cd /data/docker/mysql/conf
# 新建并编辑
$ vim mysql.cnf
insert以下内容:
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_general_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_general_ci
skip-character-set-client-handshake
// 将文件 cp 到容器指定位置,覆盖原有的配置文件
docker cp /usr/local/temp/mysql.cnf mysql容器名:/etc/mysql/conf.d/mysql.cnf
// 重启mysql
docker restart mysql容器名
// 确认编码是否成功更改
// 进入容器:
docker exec -it 容器id/容器名称 bash
// 登录mysql
mysql -uroot -p -h localhost
// sql语句查看编码
show variables like 'char%';
4、安装Redis
# 1. redis不加: 版本号, 默认pull的是最新版本
$ docker pull redis
# 2. 新建宿主机目录
mkdir -p /data/docker/redis
# 3. cd
cd /data/docker/redis
# 4. 下载 原始redis.conf 文件
$ wget http://download.redis.io/redis-stable/redis.conf
# 5. 更改 宿主机上的redis.conf 文件的权限
chmod 777 redis.conf
# 6. 编辑宿主机上的redis.conf
# 这行要注释掉,解除本地连接限制,【必须设置的】
bind 127.0.0.1 --> 需要注释掉
# 保护模式是一层安全保护,以避免在互联网上打开的 Redis 实例被访问和利用。
# 当保护模式打开并且默认用户没有密码时,服务器仅允许在本机的回环连接,其他机器无法连接。
# 默认为 yes,在生产环境下一般设置为 no,这样可以避免客户端连接时出现超时或连接不上的情况。
protected-mode no
# 默认 no 为不守护进程模式,docker 部署不需要改为 yes,docker run -d 本身就是后台启动,不然会冲突【必须设置的】
daemonize no
# 设置密码,可选
requirepass 123456
# 持久化
appendonly yes
# 7. 运行
docker run -p 6379:6379 --name redis --privileged=true \
-v /data/docker/redis/redis.conf:/etc/redis/redis.conf \
-v /data/docker/redis/data:/data \
-d redis:版本号。最新的则不需要显示指定 \
redis-server /etc/redis/redis.conf \
--appendonly yes
# --name redis 为容器指定一个名称,查看和进行操作都比较方便。
# -p 6379:6379 指定端口映射,格式为:主机(宿主)端口:容器端口
# --privileged=true 开启容器卷挂载特殊权限
# Docker 挂载主机目录时(添加容器数据卷),如果 Docker 访问出现 cannot open # directory:Permission denied,在挂载目录的命令后多加一个 --privileged=true 参数即可。
# 因为出于安全原因,容器不允许访问任何设备,privileged 让 docker 应用容器获取宿主机 root 权限(特殊权限),允许我们的 Docker 容器访问连接到主机的所有设备。容器获得所有能力,可以访问主机的所有设备,例如,CD-ROM、闪存驱动器、连接到主机的硬盘驱动器等。
# -v 挂载文件或目录:前面是宿主机部分,后面是容器部分
# -d redis 表示后台启动 redis;使用此方式启动,则 redis.conf 中 daemonize 必须设置为 no,否则会无法启动
# redis-server /etc/redis/redis.conf 在容器内启动 redis-server 的命令,用于加载容器内的 conf 文件,最终找到的是挂载的目录 /data/docker/redis/redis.conf。
# --appendonly yes 开启 redis 持久化
# 8. 使用redis
docker exec -it redis容器 redis-cli
set a b
get a
4.1、redis桌面版下载
4.2、追加每次自重启
docker update redis --restart=always
八、DockerFile
Docker可以通过读取Dockerfile中的指令来自动构建镜像。Dockerfile是一个文本文档,其中包含用户可以在命令行上调用的用于组装图像的所有命令。
1、dockerfile文件编写规范
- 保留字必须全部大写,且最少要跟随一个参数;
- 指定按照从上到下,顺序执行;
- 每条指令都会创建一个新的镜像层,并对镜像进行提交;
2、dockerfile的常见保留字使用
- FROM:指定一个已经存在的镜像作为模版,dockerfile的第一条指令必须是FROM;
- MAINTAINER:镜像维护者的姓名和邮箱地址
- RUN: 容器构建时,需要运行的命令;
- shell格式
- exec格式
- EXPOSE: 当前容器对外暴露的端口;
- WORKDIR:指定登陆容器终端的默认目录;
- ENV: 用来在构建镜像中,设置环境变量,指定了变量和值;
- ADDR:copy和解压宿主机的文件到镜像;
- CMD: 指定容器启动后,要做的事;可以写多条CMD,但是只有最后一条起作用;如果docker run后面有参数,会把cmd的参数覆盖掉;CMD是在docker run时运行,RUN是在docker build时运行;
- ENTRYPOINT: 指定容器启动后,要做的事;但是不会被docker run后面的参数覆盖;如果ENTRYPOINT和CMD一起使用,CMD不再是容器启动后执行,仅仅用作对ENTRYPOINT指令的传参数;