docker 概述
1. 基础知识
1. docker 和虚拟机技术的不同
- 传统虚拟机,虚拟出一个硬件,运行整个完整的操作系统,然后在这个系统上部署软件
- 容器内的应用直接运行在宿主主机上,没有自己的内核,也没虚拟硬件。且容器间是相互独立的,每个容器内都有自己的文件系统,互不影响。
2. docker 的特点
- 应用更快速的交付
- 更便捷的升级和扩容
- 更简单的系统运维
- 更高效的计算资源利用
3. docker 架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cC4OLzoI-1653055781765)(C:\Users\86134\AppData\Roaming\Typora\typora-user-images\image-20210517201203814.png)]
4. 什么是容器数据卷
- 当我们删除容器后,容器内的数据也会跟着被删除。为了能够在容器删除后还能保留数据的需求下,应运而生了一个数据共享技术,这就是卷技术。
- docker 容器中产生的数据同步到本地就是容器数据卷。即将容器的目录挂载到本地服务器。
2. docker 部署
-
卸载旧版本 docker
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
-
配置
yum
源yum install -y yum-utils yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum makecache fast
-
安装
docker
yum install -y docker-ce docker-ce-cli containerd.io
-
配置docker网卡
$ yum install bridge-utils -y # 安装网卡工具 $ ip link set dev docker0 down # 将 docker0 网卡停掉 $ brctl delbr docker0 # 将 docker0 删掉 $ brctl addbr docker0 # 增加一块 docker0 网卡 $ ip addr add 172.16.10.1/24 dev docker0 # 配置网卡 ip 地址 $ ip link set dev docker0 up # 启动网卡 $ip addr # 查看 ip 地址信息,有没有 docker0 网卡
-
启动并检测docker
systemctl start docker docker run hello-world ## Hello from Docker 即为成功!
-
配置阿里云加速器
1. 登录阿里云,点击左上角的`三个横线`,选择`产品与服务`,选择`容器镜像服务`,`镜像工具`--->`镜像加速器` sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://ujhbdxl8.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
3. docker 常用命令
-
官方手册
https://docs.docker.com/engine/reference/commandline/port/ -
系统命令
docker version # 显示 docker 版本信息 docker info # 显示 docker 的系统信息,包括镜像和容器的数量
1. 镜像命令
1. 查看本地镜像
`docker` images # 查看本地有多少镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
# 镜像的仓库源 标签 镜像ID 镜像创建的时间 镜像大小
`docker` images --help
# Options:
-a, --all # 列出所有的镜像
-q, --quiet # 只显示镜像 ID
2. 搜索镜像
`docker` search image-name
`docker` search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
# 镜像名字 镜像的描述 收藏数 是否官方发布 是否自动更新镜像仓库的镜像
`docker` search --help
# Options:
-f, --filter filter # 根据相应信息进行过滤,示例如下:
`docker` search -f stars=3000 mysql # 列出收藏数大于3000的
`docker` search -f is-automated=true mysql # 列出是官方发布
`docker` search -f is-official=true mysql # 列出是自动更新镜像仓库的
--format string # 以什么形式输出,示例如下:
`docker` search --format "{{.Name}}: {{.StarCount}}" nginx
nginx: 14875
`docker` search --format "table {{.Name}}\t{{.IsAutomated}}\t{{.IsOfficial}}" nginx
NAME AUTOMATED OFFICIAL
nginx [OK]
--limit int # 列出多少列(默认 25),示例如下
`docker` search --limit 3 mysql
3. 下载镜像
`docker` pull [options] name[:tag|@digest]
# 选项基本没什么用
# 示例如下
docker pull mysql
Using default tag: latest # 不指定 tag 将下载最新的
latest: Pulling from library/mysql
69692152171a: Pull complete # 分层下载,docker镜像基本都是由多层组成(分层存储),每一层都可以被不同镜像共同使用
Digest: sha256:d50098d7fcb25b # 有时候你可能并不想获取最新的镜像文件,而是使用一个固定版本的镜像文件。docker提供了一种通过摘要digest拉取镜像的方式,这种方式你可以明确的指定镜像的版本号。这样你可以获得一个固定版本的镜像文件。并且确保你每次使用的时候都是同一个镜像文件。
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
4. 删除镜像
docker rmi image-id # 删除指定镜像
docker rmi ${docker images -qa} # 删除全部
5. 镜像改名
`docker` tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
7. 具名挂载和匿名挂载
-
具名挂载
`docer` run -v nginx01:/etc/nginx nginx002 # 查看全部挂载 `docker` volume ls DRIVER VOLUME NAME # local nginx001 # 查看挂载目录 `docker` inspect nginx001 | grep -A8 "Mounts" "Mounts": [ { "Type": "volume", "Name": "nginx001", "Source": # "/var/lib/docker/volumes/nginx001/_data", "Destination": "/etc/nginx", "Driver": "local", "Mode": "z", "RW": true,
-
匿名挂载
docker run -v /etc/nginx/ nginx:stable ## 没有具体的名字,不常用!
-
容器之间进行数据共享
docker run --vlumes-from mysql001 mysql:5.7 --name mysql002 # 如果 mysql001 是将 /var/lib/mysql 挂载到本机上,那么 mysql002 也的 /var/lib/mysql 目录,也会挂载到本机上,实现 mysql 之间的数据共享。
6. 实现两个容器间进行数据共享
-
创建第一个容器时,部署容器和主机的共享目录
-
创建新的容器时进行数据共享
`docker` run --volumes-from docker01 centos
2. 容器命令
1. 运行(创建)、开启、关闭、进入、退出容器
-
创建容器
docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...] # 不加tag,默认最新 # 参数说明 --name="Name" # 给容器起名字 -d # 在后台运行,容器后台启动,就必须有一个前台的进程 -it # 使用交互的方式运行,进入容器查看内容 -p 主机端口:容器端口 # 主机端口映射到容器端口 -p IP:主机端口:容器端口 # 主机端口映射到容器端口 -p 容器端口 # 外面访问不到该端口 容器端口 # 外面访问不到该端口 -e "discovery.type=single-node" # 单机使用容器 安装es -e ES_JAVA_OPTS="-Xms265m -Xmx512m" # 设置内存使用量 安装es -e MYSQL_ROOT_PASSWORD=mysql # 设置 MySQL 密码为 mysql -v 本机目录:容器目录:读写权限[ro rw] # 设置容器挂载目录,读写权限若设置了 ro 则只能在主机上进行操作了 -v /home/mysql/conf:/etc/mysql/conf.d # 将 MySQL 的配置文件目录挂载到本地的 /home/mysql/conf 下 -v /home/mysql/var/date:/var/lib/mysql # 将 MySQL 的存储目录挂载到本地的 /home/mysql/var/data 下 --net mynet # 将容器加入到 mynet 网络模式 ### 示例如下: docker run -it centos:7 /bin/bash # 启动容器并进入容器
-
启动和停止容器
`docker` start 容器ID # 启动容器 `docker` restart 容器ID # 重启容器 `docker` stop 容器ID # 停止容器 `docker` kill 容器ID # 强制停止
-
进入当前正在运行的容器
`docker` exec -it 容器ID /bin/bash # 打开一个新的窗口 `docker` attch 容器ID # 进入运行的窗口
-
退出容器
exit # 直接退出容器 Ctrl + p + q # 退出容器不停止
-
删除容器
`docker` rm -f 容器id # 删除指定容器
2. 列出所有运行的容器
`docker` ps # 列出正在运行的容器
`docker` ps -a # 列出运行过和正在运行的容器
`docker` ps -n=1 # 列出一行
`docker` ps -q # 只显示 id
3. 查看容器相关信息
-
查看容器的系统日志
`docker` logs [options] 容器ID `docker` logs --help # Options: --details # Show extra details provided to logs -f, --follow # 和 Linux tail -f 一样 --since string # Show logs since timestamp -n, --tail string # 打印多少行(默认全部) -t, --timestamps # 显示时间戳 --until string # 显示日志在一个时间戳后
-
查看容器中的进程信息
`docker` top 容器id
-
查看镜像的元数据
`docker` inspect 容器ID
4. 从容器内拷贝文件到主机
docker cp 容器ID:/root/a.txt ./ # 从容器中拷贝 a.txt 文件到主机的当前目录下
docker cp ./a.xt 容器ID:/root/ # 拷贝当前目录下的 a.txt 到容器中的 /root 目录
5. commit 镜像
`docker` commit -m "提交的描述信息" -a "作者" 容器id 目标镜像名:[tag]
### 举例:
docker commit -m "it is a private nginx for codefun." -a "codefun" 2890096b3958 nginx:codefun
4. 项目案例部署
1. docker 部署 portainer
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- 网页访问 ip:8088 即可
2. docker 部署 Nginx
-
查找
Nginx
镜像,建议在dockerhub
上,网址如下:
https://hub.docker.com/ -
拉取镜像,建议使用稳定版本
stable
`docker` pull nginx:stable
-
创建
nginx
容器`docker` run --name="nginx001" -p 80:80 nginx:stable
-
启动容器并测试是否安装成功
`docker` start nginx001 curl localhost:80
3. centos7 安装 ssh
vim /dockerfile/centos_ssh --------------------------------------------------- FROM centos:7 MAINTAINER This is centos:ssh RUN yum update -y && yum install -y openssh-server net-tools lsof telnet passwd RUN echo "123456" | passwd --stdin root RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key RUN sed -i '/^session\s\+required\s\+pam_loginuid.so/s/^ /#/' /etc/pam.d/sshd RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh EXPOSE 22 CMD ["/usr/sbin/sshd","-D"] ---------------------------------------------------- docker build -f /dockerfile/centos_ssh -t codefun001/centos_ssh:v1 .
4. docker 部署 registry
-
拉取并生成容器
`docker` run -d -P --restart=always --name reg -v reg:/var/lib/registry registry
-
编写配置文件
cat /etc/docker/daemon.json -------------------------------------------------------------------- { "registry-mirrors": ["https://ujhbdxl8.mirror.aliyuncs.com"], "insecure-registries": ["192.168.80.141:49153"] } --------------------------------------------------------------------
-
上传和下载镜像
`docker` tag nginx:latest 192.168.80.141:49153/codefun/nginx01:v1 # 注意名字的格式 `docker` push 192.168.80.141:49153/codefun/nginx01:v1 `docker` pull 192.168.80.141:49153/codefun/nginx01:v1
-
用户认证
`docker` run -d -p 5000:5000 -v regauth:/auth/ -v reglib:/var/lib/registry --name reg -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" registry # 添加用户认证功能 `yum` install -y httpd-tools # 下载用户认证工具 `htpasswd` -Bbn codefun 123 > /var/lib/docker/volumes/regauth/_data/htpasswd # 添加用户 `docker` login 192.168.80.141:5000 # 进行登录 `docker` push 192.168.80.141:5000/codefun/nginx01:v1 # 推送镜像 `docker` logout
5. harbor 部署
安装 docker-compose :
https://github.com/docker/compose/releases/download/1.15.0/docker-compose-Linux-x86_64
(一)下载安装包,重命名为docker-compose,放入/usr/local/bin,
(二)
chmod +x /usr/local/bin/docker-compose # 增加可执行权限
(三)
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 创建软连接,使其可以直接运行
安装 harbor:
https://github.com/vmware/harbor/releases/download/v1.1.1/harbor-online-installer-v1.1.1.tgz
(一)下载压缩包,解压并进入
harbor
目录,(二)修改 harbor.cfg 文件:
hostname = 192.168.80.141 # 修改为自己的IP地址
(三)将仓库容器的5000端口映射到主机的5000端口,修改
docker-compose.yml
文件 :registry: # 注意:是 registry: 下 image: vmware/registry:photon-2.6.0 container_name: registry restart: always volumes: - /data/registry:/storage:z - ./common/config/registry/:/etc/registry/:z ports: - 5000:5000 # 这个是在 volumes 和 networks 之间添加的两行 networks: - harbor
(四)执行安装脚本
./install.sh
(五)检测是否成功
docker ps # 有大量容器启动
在网页上访问 http://192.168.80.141:80 用户名为:
admin
,密码为:Harbor12345
在 Linux 上进行上传镜像:
`docker` login 192.168.80.141:5000 `docker` pull busybox `docker` tag busybox:latest 192.168.80.141:5000/library/busybox:test `docker` push 192.168.80.141:5000/library/busybox:test
5. dockerFile[^1]
1. 整体操作流程
-
编写 dockerFile 文件
-
docker build
构建成一个镜像`docker build` -f dockerfile_path -t image_name:tag `.` ## 不要忘记后面有个小点 `docker build` -f /dockerfile/centos -t centosfun:gx `.` # 示例
-
docker run
运行镜像,建立容器 -
docker push
将镜像发布到 dockerhub1. ## 在 dockerhub 上注册用户 2. ## 在主机上进行登录 `docker` login -u codefun001 3. ## 将镜像上传到 dockerhub `docker` push image_name:tag # 注意:镜像名字的格式必须为 dockerhub用户名/image_name
-
将镜像发布到阿里云
- 找到
容器镜像服务
,点击实例列表
,创建个人实例 - 点击
命名空间
,进行相关配置 - 点击
创建镜像仓库
,进行相关配置 - 根据网页提示进行操作即可
- 找到
2. dockerFile 指令
FROM image-name:tag # 基础镜像,以那个镜像为基础创建新的镜像 FROM centos:7 # 示例
MAINTAINER creator-name # 指定维护者信息 MAINTAINER codefun # 示例
RUN shell-command # 镜像构建时需要运行的指令 RUN yum install -y vim # 示例
ADD source dest # 向镜像中添加一些配置文件 ADD /tmp/a.txt /tmp # 将主机内 /tmp/a.txt 添加到容器 /tmp/ 目录下 ## 注意:add 和 copy 的区别,add 会自动解压 tar、gzip、bzip2 文件,官方推荐我们使用 copy,因为解压是非常费事的。
COPY source dest # 将文件拷贝到镜像中 COPY /tmp/a.txt /tmp # 将主机内 /tmp/a.txt 添加到容器 /tmp/ 目录下
WORKDIR dir-path # 镜像的工作目录 WORKDIR /usr/local # 示例
VOLUME ["<dir_path1>", "<dir_path2>"...] # 和主机共享的目录 VOLUME /tmp # 示例
EXPOSE port_name1 port_name2 # 向外暴露那个端口,但是还未和主机建立联系 EXPOSE 80 # 示例
CMD shell_command # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 CMD systemctl start nginx # 容器启动的时候,启动 nginx `docker run` 后面追加的命令会将 `CMD` 的命令进行覆盖。 若在 dockerfile 中写入的是`CMD ls`,则使用 `docker run xxx -l` 创建容器后,容器就会执行 `-l`命令。
ENTRYPOINT shell_command # 指定这个容器启动的时候要运行的命令,可以追加命令 ENTRYPOINT systemctl start nginx # 容器启动的时候,启动 nginx `ENTRYPOINT`会追加`docker run` 后面追加的命令。 若dockerfile 中写入`ENTRYPOINT ls`, 则使用 `docker run xxx -l` 创建容器后,容器就会执行 `ls -l`命令。
ONBUILD # 当构建一个被继承 dockerfile 时,就会运行这个命令### 语法:若指令后面跟多个参数,则需要用中括号括起来。
ENV key1=value1 key2=value2 # 构建的时候设置环境变量 ENV MYSQL_ROOT_PASSWORD=mysql # 在创建 mysql 或者 es 的时候用到
3. dockerfile 示例
-
构建一个普通的镜像
cat /dockerfile/centos -------------------------------------------------------------------- FROM centos:7 MAINTAINER codefun RUN yum install -y vim RUN yum install -y net-tools CMD echo "it is already installed" WORKDIR /tmp VOLUME ["/tmp"] EXPOSE 80 CMD echo "it is already OK" --------------------------------------------------------------------
6. docker 网络
1. 基本原理
- Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势之一是转发效率较高。
- Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发。
- docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做
veth pair
)。
2. docker 网络模式
-
host
模式- 与宿主机在同一个网络中,但没有独立IP地址。
- 容器不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。
- 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
-
container
模式- 这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。
- 新创建的容器会和一个指定的容器共享IP、端口。
- 两个容器的进程可以通过lo网卡设备通信。
-
bridge
模式- 容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)。
- 为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上
- 缺点:不能用容器的主机名互相访问
-
none
模式- 不设置网络,保护容器的数据安全。
3. 自定网络
-
docker network
命令详解`docker` network --help # Commands: -connect # 使用指定的网络模式 `docker` network connect mynet container01 # 指定 container01 使用 mynet 网络 -create # 创建网络模式 `docker` network create --driver bridge --subnet 182.168.0.0/16 --gateway 182.168.0.1 mynet # 创建名为 mynet 的网络模式,网络范围为 182.168.0.1 ~ 182.168.254.254,网关为 182.168.0.1,连接方式为桥接。 -disconnect # 取消使用指定的网络模式 `docker` network disconnect mynet container01 # 取消 container01 使用 mynet 网络 -inspect # 显示网络模式的详细信息 `docker` network inspect mynet # 显示 mynet 网络的详细信息 ls # 列出所有的网络模式 `docker` network ls # 列出所有的网络模式 prune # 删除所有没有用的网络模式 rm # 删除指定的网络模式
-
创建自定义网络模式
`docker` network create --driver bridge --subnet 182.168.0.0/16 --gateway 182.168.0.1 mynet # 返回 docker 部署,配置 docker 网卡
-
创建容器并加入自定义网络模式
`docker` run -d -P 0 --net mynet --name tomcat001 tomcat `docker` run -d -P 0 --net tomcat002 tomcat
-
使 tomcat001 能够 ping 通 tomcat002
`docker` network connect bridge tomcat001
-
自定义网络的优点
自定义网络和 docker 自带的网络模式中的 bridge 模式的基本原理相同,但是自定义网络修复了**容器名直接互相 ping **的缺点。
普通用户使用 docker 设置
方法一:赋予普通用户root权限
vim /etc/sudoers
---------------------------------------------
root ALL=(ALL) ALL
name1 ALL=(ALL:ALL) ALL # 使用 sudo 时,需要 name1 密码
name2 ALL=(ALL:ALL)NOPASSWD: ALL # 使用 sudo 时,不需要 name1 密码
----------------------------------------
## 注意:需要按 wq! 才能保存退出。
# 不用刷新 sudoers 文件,即时生效。
方法二:添加 docker 组
-
查看是否有 docker 组
cat /etc/group | grep docker
- 没有就添加
groupadd docker
- 没有就添加
-
查看
/var/run/docker.sock
的属性ls /var/run/docker.sock
,正确的应该是root docker
- 不正确就修改:
chgrp docker /var/run/docker.sock
- 不正确就修改:
-
将普通用户添加至 docker 组
gpasswd -a test docker id test # 查看是否添加成功 newgrp docker # 没有成功就刷新 docker 组 newgrp test # 最后切回原组
-
将用户从 docker 组中删除
gpasswd -d test docker newgrp doker # 此时 id test 显示已经删除了,但是该用户若正在连接,还是可以使用 docker,只需要断开连接再次重连即可。 # 若他不重连,则直接杀死该连接 w # 查看当前终端的使用情况 17:19:24 up 1:17, 2 users, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.154.1 16:03 4.00s 0.19s 0.01s w gongxian pts/1 192.168.154.1 17:19 7.00s 0.01s 0.01s -bash pkill -kill -t pts/1 # 杀死该连接 pkill -9-t pts/1 #上面的不行,强制杀死