Docker - 学习笔记
Docker
docker 的出现开启了一个新的时代:容器化时代
市面上有很多开发语言,如:Java、C++、JavaScript,如果你要运行,你可能拿到的是一个 .jar
.exe
.sh
文件甚至你需要自己编译源码。没有一个统一的标准进行管理。
而 Docker 却可以将这些应用 build 成一个镜像,你只要是一个 Docker 镜像,那么 Docker 就可以直接给你跑起来。不仅如此, 这些镜像还很容易分享,例如将某些镜像放到指定的地方,别人就可以找到这个镜像下载和运行,所以 Docker 的推出还统一了标准。
虚拟化技术
在 Docker 之前,非常流行一种“虚拟化技术”,这种技术其实就是在一台机器中安装多个虚拟机,我们部署的应用都在这些安装的虚拟机中。如果有应用出现问题,比如内存泄露,顶多把他自个的机子内存占满,不会影响到别的应用。
虚拟化技术有一下痛点:
- 基础镜像GB级别
- 创建使用比较复杂
- 启动速度慢
- 移植与分享不方便
优点是隔离性很强
容器化技术
- 基础镜像MB级别
- 创建简单
- 隔离性强
- 启动速度秒级
- 移植与分享方便
架构
Docker_Host
如果需要使用 Docker,那么需要在使用的机器上安装 Docker。安装了 Docker 的机器称为 Docker 主机。
Docker Daemon
安装了 Docker 后,主机启动那么后台就会启动一个 Docker 的进程
Docker Daemon
Client
如果需要操作 Docker,那么需要使用命令行,这个命令行被称为Docker 客户端Images
镜像,一个带环境打包好的程序,可以直接启动运行
Registry
镜像仓库,官方的镜像仓库是 Docker HubContainers
容器,由镜像启动起来正在运行中的程序
Docker 安装
卸载旧版
1 | sudo yum remove docker \ |
设置 Docker yum 源所在的位置
1 | sudo yum install -y yum-utils |
安装 Docker
1 | sudo yum -y install docker-ce docker-ce-cli containerd.io |
安装成功后将 docker 设置为开机启动
1 | [root@i-ul0sb6hn ~]# systemctl enable docker --now |
国内使用默认的镜像仓库可能会很慢,我们可以替换成阿里云的地址,registry-mirrors
用你自己的就行
1 | sudo mkdir -p /etc/docker |
镜像操作
下载镜像
可以到中央镜像仓库 https://hub.docker.com/
找你需要的镜像。
第一步首先找到你需要的镜像然后点击进去
右边会有一个下载命令,我们可以直接使用这个命令来下载这个容器,这命令默认是下载的最新版本。
可以点 tags 来找你需要的版本
找到需要的版本后,可以使用 docker pull <image>:<tag>
命令下载,在 Docker 中,版本名还被称为标签
1 | docker pull nginx:1.21.6-perl |
查看已下载的镜像
可以使用 docker images
命令查看已下载的镜像
1 | [root@i-ul0sb6hn ~]# docker images |
删除镜像
可以使用 docker rmi <image>:<tag>
命令移除镜像
1 | [root@i-ul0sb6hn ~]# docker rmi nginx |
再检查镜像列表,就可以看到已经被移除了
1 | [root@i-ul0sb6hn ~]# docker images |
启动容器
在下载了一个镜像后,可以使用 docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
启动指定镜像
例如启动一个 nginx
1 | docker run --name=nginx -d --restart=always nginx:latest |
--name
启动别名-d
后台启动--restart
容器是否开机自启,默认是no
,如果需要设置为开启自启,可以设置为always
查看正在运行的容器
如果需要查看正在运行的容器,可以使用 docker ps
进行查看
1 | [root@i-ul0sb6hn ~]# docker ps |
删除容器
删除一个已经停止的容器,通过这个命令 docker rm <container_id | name>
1 | docker rm nginx |
停止一个正在运行的容器
docker stop <container_Id | name>
命令可以停止一个正在运行的容器
1 | docker stop nginx |
启动已停止运行的容器
使用 docker start <container_Id | name>
命令
1 | docker start nginx |
修改已启动容器的设置项
docker update [OPTIONS] CONTAINER [CONTAINER...]
,例如将一个容器修改为开启自启
1 | docker update nginx --restart=always |
端口映射
docker 容器其实是一个小的Linux,里面的nginx暴露了一个端口为80,但是它不是在我们主机上暴露的,所以我们无法通过 ip 去访问这个nginx。需要在 docker 做一层端口映射,将主机的某个端口映射到 docker 容器中的指定端口上。
1 | docker run --name=nginx -d -p 88:80 nginx |
启动后检查 PORTS
是不是成功的
1 | [root@i-ul0sb6hn ~]# docker ps |
进入容器
如果需要修改容器的配置或者什么东西,由于 Docker 的资源隔离是非常高的,所以不能直接修改,需要进入这个容器的控制台,类似 ssh 远程连接某个服务器。
1 | docker exec -it nginx /bin/bash |
1 | [root@i-ul0sb6hn ~]# docker exec -it nginx /bin/bash |
进到容器后,可以找到例如nginx的部署目录并修改内容
1 | root@8e6d1342b9e8:/# cd /usr/share/nginx/html |
修改后刷新浏览器访问
改完后直接使用 exit
退出即可
提交改变
可以将自己已经修改好的镜像提交,例如配置nginx容器,配置了很多次配好了,如果移到新的服务器上,还需要重新配置。那么可以使用 docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
命令将当前容器重新生成为一个新的镜像。
1 | [root@i-ul0sb6hn ~]# docker commit -a "Clover You" -m "修改index.html" nginx clover-nginx:v0.0.1 |
可以再检查一下已下载的镜像
1 | [root@i-ul0sb6hn ~]# docker images |
测试一下,将之前在运行的nginx删掉,直接运行我们刚刚 commit 的镜像
1 | docker run -d -p 88:80 --name=clover-nginx clover-nginx:v0.0.1 |
再访问,它保留了我们上次修改容器的结果
镜像传输
当我们做好一个镜像后,如果我们需要给别人分享,有两种办法,一种是物理传输,还有一种是推送至远程仓库。
可以先使用 docker save [OPTIONS] IMAGE [IMAGE...]
命令将镜像压缩
1 | [root@i-ul0sb6hn ~]# docker save -o clover-nginx.tar clover-nginx:v0.0.1 |
之后直接将 clover-nginx.tar
分享出去就行了
再通过 docker load [OPTIONS]
命令加载这个镜像
1 | [root@i-ul0sb6hn ~]# docker load -i ./clover-nginx.tar |
检查镜像
1 | [root@i-ul0sb6hn ~]# docker images |
推送到远程仓库,先创建一个镜像仓库
填好仓库信息后点【create】就好
给我们本地镜像加个标签 docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
1 | docker tag clover-nginx:v0.0.1 cloveryou/clover-nginx:v0.0.1 |
最后通过 docker push
命令将镜像推送
1 | docker push cloveryou/clover-nginx:v0.0.1 |
以上操作是需要登录的,如果没有登录需要使用 docker login
登录
1 | [root@i-ul0sb6hn ~]# docker login -u <user name> -p <password> |
登录成功后再重新推送
推送成功刷新仓库就可以看到了
如果是公开的仓库,也可以通过搜索搜到
最后需要用就直接下载就好啦
1 | docker pull cloveryou/clover-nginx:v0.0.1 |
挂载数据到外部
像我们之前修改nginx,是需要进入到容器里修改,其实可以将容器中的某个文件夹挂载到主机的某个位置。docker run --name=xxx -d -v [target path]:[source path]:[缺省,ro容器内只读,rw容器内可读写]
1 | docker run --name=clover-nginx -d -p 88:80 -v /data/html:/usr/share/nginx/html:ro clover-nginx:v0.0.1 |
-v
将容器中某个目录挂在到主机上,如果挂载的是一个文件,那么这个文件在主机上必须存在
启动后我们只要在主机的 /data/html
检查容器日志
docker logs <container>
复制容器文件到主机
docker cp <container>:<source path> <target path>
例如将nginx中的文件复制出来
1 | docker cp 52924565fcfc:/etc/nginx /data/nginx |
1 | [root@i-ul0sb6hn data]# ls |
然后将nginx的配置文件挂载到本地
1 | docker run --name=clover-nginx -d -p 88:80 \ |
将现有应用打包成 Docker 镜像
以 SpringBoot 为例,先将我们的项目打包成 .jar
包。然后编写一个 Dockerfile
将这个 .jar
打包成 Docker 镜像。
1 | FROM openjdk:8-jdk-slim |
由于 Docker 镜像都是一个很小的 Linux 系统,并没有我们的运行环境,所以需要指定安装jdk环境 openjdk:8-jdk-slim
。
然后将项目打包结果复制到 Linux 的某个位置,ENTRYPOINT
用于 Docker 启动时执行的命令,也可以使用 CMD
。让 Docker 启动时执行 java -jar /app.jar
启动我们的项目。
Dockerfile 文件编写好后,需要到一个有 Docker 环境的机子上执行。
执行 docker build [OPTIONS] <工作路径>
命令打包
1 | docker build -t spring-boot-hello-world:v1.0.0 . |
注意:如果出现以下错误,那是因为 Dockerfile 不能放在 /
目录
1 | error checking context: 'file ('/proc/1500/fd/7') not found or excluded by .dockerignore'. |
打包完成后查看镜像,就可以看到我们打包的镜像
1 | [root@i-ul0sb6hn ~]# docker images |
启动容器
1 | docker run -d -p 80:8080 --name=helloworld spring-boot-hello-world:v1.0.0 |
检查是否启动成功
1 | [root@i-ul0sb6hn ~]# docker ps |
然后访问我们的服务就可以了