Docker概述

环境配置问题

问题:为什么这个程序在我的电脑上可用运行,在另一台电脑上无法运行?

Java程序必须安装JDK才可以编译运行,如果另一台电脑没有JDK就无法运行了

那有什么办法可以解决这个呢?

项目可以带上环境(镜像)安装打包,这样就可以避免这个问题

镜像与容器

镜像(image):

docker镜像好比是一个模板,可以通过这个模板来创建容器(最终项目运行是在容器中的)

容器(container):

容器就是一个简易版的Linux

举例:

MySQL01容器:就是一个简易版的Linux系统上安装了一个MySQL

如何避免环境问题

  • 假如你现在有一个Java项目,里面运用了MySQL,Redis,RabbitMQ等技术

  • 那么你把这个项目打包成一个镜像给另一个人

  • 另一个人直接用这个镜像创建一个容器就可以在自己上面运行了,避免环境问题

  • 这相当于直接创建了一个Linux,在Linux上面部署了这些环境,从根源上就帮你把环境配置好了,不需要在本机上配置

总结

  • Docker是基于go语言开发的

docker的好处:

  1. 部署非常块:只需要拉取镜像,生成容器就部署完成,不需要配环境

  2. 资源消耗少:其镜像都是精简版,只针对环境部署那部分

docker安装

安装

  1. 卸载旧版本的 Docker(如果已安装)

 yum remove docker \
 docker-client \
 docker-client-latest \
 docker-common \
 docker-latest \
 docker-latest-logrotate \
 docker-logrotate \
 docker-selinux \
 docker-engine-selinux \
 docker-engine \
 docker-ce
  1. 安装必要的依赖

 yum install -y yum-utils device-mapper-persistent-data lvm2
  1. 添加 Docker 的阿里云YUM仓库(官方仓库无法访问的)

 yum-config-manager \
 --add-repo \
 http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 安装 Docker CE(社区版)

 yum install -y docker-ce docker-ce-cli containerd.io
  1. 启动 Docker 服务并设置开机自启

 systemctl start docker
 systemctl enable docker
  1. 验证 Docker 是否安装成功

 docker run hello-world

如果看到欢迎消息,说明 Docker 已成功安装。

配置国内镜像加速

为了提高镜像拉取速度,可以配置国内的 Docker 镜像加速器,例如阿里云镜像加速器:

 sudo mkdir -p /etc/docker
 sudo tee /etc/docker/daemon.json <<-'EOF'
 {
   "registry-mirrors": ["https://your_mirror.aliyuncs.com"]
 }
 EOF
 sudo systemctl daemon-reload
 sudo systemctl restart docker

your_mirror 替换为实际的加速器地址。

docker常用命令

帮助文档的地址 https://docs.docker.com/reference/

  1. docker images:显示本地镜像

  2. docker images -aq:-a显示所有镜像,-q只显示镜像id

  3. docker search 镜像名:搜索镜像,目前访问不了docker hub,所以这里无法search到,可以去网站上看

  4. docker pull 镜像名:tag :拉取镜像,如果不写 :tag 那么默认最新版(例如docker pull nginx:1.18.0)

  1. docker rmi -f IMAGE ID:强制删除镜像,即使有容器存在。但是如果有其他镜像依赖他,则会报错

  2. docker rmi IMAGES ID : 删除镜像,但如果有容器存在则报错

  3. docker rmi -f $(docker images -aq):删除所有镜像

 docker run [可选参数] image
 ​
 #参数说明
 --name="Name"   容器名字 tomcat01,tomcat02,用来区分容器
 -d      后台方式运行
 -it     使用交互方式运行,进入容器查看内容
 -p      指定容器的端口 -p 8080:8080
 -P      随机指定端口(大写的P)
 #例如
 [root@andrew ~]# docker run -it --name centos01 5d0da3dc9764 /bin/bash
 # exit退出
  1. exit :容器停止并且退出

  2. Ctrl + P + Q:容器不停止且退出

  3. docker rm 容器id : #删除指定容器,不能删除正在运行的容器

  4. docker rm -f $(docker ps -aq): #删除所有容器

  5. docker start 容器id:启动容器

  6. docker restart 容器id:重启容器

  7. docker stop 容器id:停止当前正在运行的容器

  8. docker kill 容器id:强制停止容器

  9. docker查看日志命令

#-f	指实时更新
#-n	显示几条(默认all)
#-t	显示时间戳
docker logs -tf -n 10 容器id
  1. docker inspect 容器id:查看容器的详细信息

  2. 进入容器

#我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置

#方式1
docker exec -it 容器id /bin/bash

#方式2
docker attach 容器id

#docker exec 进入容器后开启一个新的终端,可以在里面操作
#docker attach 进入容器正在执行的终端,不会启动新的进程
  1. docker cp 容器id:容器内路径 主机路径:把容器内的文件拷贝到主机上

[root@andrew home]# docker cp 6864e139dda1:/home/andrew/copytest.txt /home/andrew
Successfully copied 1.54kB to /home/andrew

练习

安装centos

[root@andrew ~]docker pull centos
[root@andrew ~]docker run -it --name centos001 centos
#-it指开启交互,并且开启伪终端

当你运行一个 Docker 容器时,如果不使用 -it 选项,容器可能会立即退出。这是因为容器开启时会执行默认命令,一旦该命令执行完成,容器就会停止运行。

例如,如果你运行一个简单的命令,如 echo "Hello, World!",命令执行完成后,容器就会退出,因为它没有更多的工作要做。

CentOS 镜像的默认命令是 /bin/bash,它会启动一个 Bash shell。如果没有 -it 选项,容器会尝试启动一个非交互式的 Bash shell,但由于没有终端连接,Bash shell 会立即退出,导致容器停止运行。

安装MySQL

[root@andrew ~]docker pull mysql
[root@andrew ~]docker run -e MYSQL_ROOT_PASSWORD=password mysql
#-e MYSQL_ROOT_PASSWORD=password:对于mysql,需要指定root用户的密码才可以成功启动

安装nginx

[root@andrew ~]docker pull nginx
[root@andrew ~]docker run -d --name nginx001 -p 3344:80 nginx
[root@andrew ~]curl localhost:3344
#记得把安全组打开
#通过访问Linux的4433端口即可访问nginx服务(nginx默认端口时80)

为什么docker可以避免环境问题

镜像与容器的

  • Docker镜像可以理解为一个模板

  • Docker容器就是基于镜像创建出来的实例

  • 是不是和类与对象很像,但是docker的镜像删除后,容器仍然可以正常使用

如何避免环境问题

  • 每一个docker容器与其他容器是隔离的,与宿主机也是隔离的

  • docker镜像中已经包含了程序运行的所有依赖

MySQL举例

对于 MySQL 镜像来说,它包含了:

  • MySQL 数据库软件:包括 MySQL 服务器和客户端工具。

  • 操作系统环境:通常是基于轻量级的操作系统(如 Alpine Linux 或 Debian)。

  • 配置文件:预设的 MySQL 配置文件。

  • 依赖库:运行 MySQL 所需的所有依赖库。

Docker 容器运行时会创建一个独立的运行环境,与宿主机和其他容器隔离。这意味着:

  • 文件系统隔离:容器有自己的文件系统,不会受到宿主机文件系统的影响。

  • 网络隔离:容器有自己的网络接口,通过端口映射与宿主机通信。

当你运行一个包含 MySQL 的 Docker 容器时,容器内的 MySQL 服务会监听某个端口(通常是 3306)。为了从宿主机访问容器内的 MySQL,你需要将容器的端口映射到宿主机的某个端口。例如:

docker run -d -p 3306:3306 --name my-mysql mysql
  • -p 3306:3306 表示将容器的 3306 端口映射到宿主机的 3306 端口。

  • 这样,你就可以通过宿主机的 3306 端口访问容器内的 MySQL 服务了。

commit镜像

将自己的容器打包为一个新的镜像(反过来)

# 命令和git原理类似
# docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
docker commit -m="mysql原封不动提交" -a="andrew" 64ae9d33dcb7 mysql_commit:001

容器数据卷

问题:如果数据都在容器中,那么删除容器,数据就会丢失

我们需要将容器中的数据存储在本地

我们可以通过卷技术,将容器的目录挂载到本地,实现数据同步

指定路径挂载

[root@andrew home]docker run -it --name centos002 -v /home/test:/home centos /bin/bash
[root@andrew home]docker inspect centos002

匿名挂载

[root@andrew ~]docker run -it --name centos003 -v /home centos
#-v 容器内路径(-v /home)
#匿名挂载中主机的默认挂载目录是 /var/lib/docker/volumes/卷名/_data

具名挂载

[root@andrew volumes]docker run -it --name centos004 -v centos004:/home centos
#-v 卷名:容器内路径
#具名挂载中主机的默认挂载目录是 /var/lib/docker/volumes/卷名/_data

总结

一般使用具名挂载

docker volume ls
#展示所有的卷

[root@andrew volumes]# ll
#在 /var/lib/docker/volumes 目录下ll

docker volume inspect <volume_name>
#来查看卷的具体路径

数据同步

#先绑定本地的
[root@andrew ~]# docker run -it --name centos001 -v centos004:/home centos
[root@andrew ~]# docker run -it --name centos002 --volumes-from centos001 centos
[root@andrew ~]# docker run -it --name centos003 --volumes-from centos002 centos

[root@andrew ~]# docker inspect e855a3d2dbe0(centos3)

"Mounts": [
    {
        "Type": "volume",
        "Name": "centos004",
        "Source": "/var/lib/docker/volumes/centos004/_data",
        "Destination": "/home",
        "Driver": "local",
        "Mode": "z",
        "RW": true,
        "Propagation": ""
    }
]

DockerFile

dockerfile就是构建镜像的脚本

构建步骤:

  1. 编写一个dockerfile文件

  2. docker build 构建一个成为一个镜像

  3. docker run运行镜像

  4. docker push发布镜像(Docker hub,阿里云镜像仓库)

基础知识:

  1. 关键字都是大写

  2. #为注释

FROM 		#基础镜像,一切从这里开始构建

MAINTAINER	#镜像是谁写的,姓名+邮箱

ENV			#构建的时候设置环境变量

WORKDIR		#镜像的工作目录

RUN			#镜像构建的时候需要运行的命令

ADD			#步骤,tomcat镜像,这个tomcat压缩包,添加内容

VOLUME		#挂载的目录

EXPOSE		#指定暴露端口

CMD			#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT	#指定这个容器启动的时候运行的命令,可以追加命令

实战测试

构建一个自己的centos,官方centos里没有vim命令

[root@andrew andrew]# vim dockerfile-cmd-test
FROM centos:7

ENV MYPATH /usr/local
WORKDIR $MYPATH

# 替换默认repo为阿里云repo,避免访问 mirrorlist.centos.org
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak && \
    curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
    yum clean all && yum makecache && \	
    yum -y install vim net-tools

EXPOSE 80

CMD ["/bin/bash"]

构建

[root@andrew andrew]# docker build -f dockerfile-cmd-test -t cmdtest .
#docker build指构建dockerfile
#-f dockerfile文件名
#-t 构建成的镜像名
#. 构建的上下文路径是当前路径下(一般dockerfile在哪个路径下就写哪个路径)

发布镜像到阿里云

登录阿里云到容器镜像服务创建镜像容器

[root@andrew andrew]docker login --username=aliyun4245954469 crpi-b1uw952vwkztio9k.cn-chengdu.personal.cr.aliyuncs.com
#然后输入密码即可
[root@andrew andrew]docker tag [ImageId] crpi-b1uw952vwkztio9k.cn-chengdu.personal.cr.aliyuncs.com/andrew291/andrew291:[镜像版本号]
#docker tag打标签
#ImageId指当前镜像id
#crpi-b1uw952vwkztio9k.cn-chengdu.personal.cr.aliyuncs.com/andrew291/andrew291:[镜像版本号]指远程镜像名称和版本号
[root@andrew andrew]docker push crpi-b1uw952vwkztio9k.cn-chengdu.personal.cr.aliyuncs.com/andrew291/andrew291:[镜像版本号]
#这里直接push即可

[root@andrew andrew]# docker tag 662628119993 crpi-b1uw952vwkztio9k.cn-chengdu.personal.cr.aliyuncs.com/andrew291/andrew291:1.0
[root@andrew andrew]# docker push crpi-b1uw952vwkztio9k.cn-chengdu.personal.cr.aliyuncs.com/andrew291/andrew291:1.0
docker pull crpi-b1uw952vwkztio9k.cn-chengdu.personal.cr.aliyuncs.com/andrew291/andrew291:[镜像版本号]

怎么找到呢?

登录-镜像容器服务-实例列表-镜像仓库-点击-镜像版本


比较是偷走幸福的小偷