Docker从入门到复制粘贴

Docker 安装、配置与卸载

Docker 安装

# 1.安装gcc环境
yum -y install gcc gcc-c++ && \

# 2. 卸载docker旧版本(可能之前有安装)
yum -y remove docker docker-common docker-selinux docker-engine && \

# 3. 安装依赖的软件包
yum install -y yum-utils device-mapper-persistent-data lvm2 && \

# 4. 设置stable仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo && \

# 5. 更新yum软件包索引
yum makecache fast && \

# 6. 安装Docker社区版
yum -y install docker-ce && \

# 7. 启动Docker
systemctl start docker && \

# 8. 测试是否安装成功
docker version

Docker卸载

# 1. 卸载docker之前需要先停止
systemctl stop docker && \

# 2. 卸载docker
yum -y remove docker-ce && \

# 3. 清除残留文件
rm -rf /var/lib/docker

配置Docker仓库的国内镜像加速

VAR_PATH_ETC_DOCKER_DIR="/etc/docker" && \
VAR_PATH_ETC_DOCKER_DAEMON_JSON="$VAR_PATH_ETC_DOCKER_DIR/daemon.json" && \

# 1. 创建存放配置文件的文件夹
mkdir -p $VAR_PATH_ETC_DOCKER_DIR && \

# 2. 创建配置文件
# 配置文件的具体内容因人而异, 需要登录[阿里云开发者平台](https://dev.aliyun.com/search.html)进行查看
cat << EOF > $VAR_PATH_ETC_DOCKER_DAEMON_JSON
{
    "registry-mirrors": ["https://zx8hwqme.mirror.aliyuncs.com"]
}
EOF

# 重新加载配置文件
systemctl daemon-reload && \

# 重启docker
systemctl restart docker

Docker 命令

命令分类

子命令分类子命令
Docker环境信息info、version
容器生命周期管理Create、exec、kill、pause、.restart、rm、run、start、stop、unpause
镜像仓库命令login、logout、pull、push、search
镜像管理build、images、import、load、rmi、save、tag、commit
容器运维操作attach、export、inspect、port、ps、rename、stats、top、wait、cp、diff、update
容器资源管理volume、network
系统日志信息events、history、logs

Docker 命令结构图

Docker 进程命令

命令作用
systemctl start docker启动docker服务
systemctl stop docker停止docker服务
systemctl status docker查看docker服务状态
systemctl restart docker重启docker服务
systemctl enable docker设置docker开机自启动

Docker 容器命令

容器命令作用
docker run ...基于镜像创建容器并启动(第一次使用,不能重复创建同名容器)
docker rm <容器名>删除容器
docker start <容器名或容器id>启动容器
docker stop <容器名或容器id>停止容器
docker kill <容器名或容器id>杀死容器
docker ps查看当前运行中的容器
docker ps -a查看所有容器
docker exec -it <容器名> /bin/bash进入到容器中
docker stop <容器id>停止容器
docker inspect <容器名>查看容器信息(IP 地址等)
docker port <容器名>查看容器的端口映射信息
docker attach <容器名>用途未知
docker commit <容器名>将正在运行的容器制作成一个镜像

docker commit 命令使用示例

Docker 镜像命令

镜像命令作用
docker images列出本地机器中的镜像
docker search <镜像名>在docker hub 中进行查找镜像
docker pull <镜像名>:<版本号>下载镜像,没指定版本号时默认为最新版
docker rmi -f <镜像名>:<版本号>强制删除镜像

Docker 容器数据卷

数据卷

数据卷出现的目的是为了解决以下的两个问题:

  • Docker容器删除后, 在容器中产生的数据也会随之消失
  • Docker容器和外部机器, Docker容器和Docker容器之间不可以直接交换文件

如果想要进行多个docker容器之间的数据交换, 可以将多个容器挂载到同一个数据卷(共享文件夹)

目录挂载

数据卷在宿主机上,挂载到 Docker 容器中。类似文件在U盘上,然后U盘接入到电脑中(挂载)。电脑重装系统并不会删除 U 盘中的数据,类似删除 Docker 容器并不会删除数据卷中的数据。

文件挂载通过 -v 指定参数 docker run -v <宿主机目录>:<docker容器内目录> --privileged=true

--privileged=true 表示 docker

额外的功能:

  • 限制容器内的目录只能读取,在上面的命令中添加 :ro(read only),构成 -v <宿主机目录>:<容器内目录>:ro

容器之间的数据卷继承

期望不同容器之间的挂载目录保持相同, 可以使用数据卷继承. 需要注意的是, 继承的是文件挂载的规则

--volumes-from <希望保持相同挂载规则的容器名>

数据卷的继承可以在不知道其它容器具体的挂载规则的情况下,复用该规则。继承的挂载规则是独立的,子容器的挂载规则不会因为父容器的删除而消失。

Dockfile

镜像原理

镜像是一层层文件堆叠而成,镜像是只读的,而容器是镜像上面在堆叠一层可写的文件,对于镜像生成的原始容器的操作都记录在容器层对应的文件中?

制作镜像

commit 制作镜像

对运行中的容器进行修改,然后通过 docker commit <容器名> <指定镜像名>:<指定版本号> 也可以创建镜像。这种方式的优点是简单,缺点在于不是自动化的,不适合复现。例如,在写博客教程时,读者需要按照博主相同的操作流程对 docker 容器进行修改配置,不能通过一行代码直接得到相同的环境。所以后面主要介绍通过 Dockerfile 来创建镜像。

通过 commit 方式制作的镜像不会打包挂载的数据卷吗?如果数据卷是容器和宿主机独立的两份,为什么这里又不会打包挂载的数据卷呢?数据卷是容器和宿主机共享的,正因为数据卷是宿主机的文件夹挂载在容器中(搞清楚谁挂载在谁上很重要,类比 U 盘插入电脑,数据卷挂载在容器中),数据卷不属于docker的文件系统,因此容器被打包成镜像时不会打包挂载的数据卷。

Dockerfile 制作镜像

Dockerfile 文件中的每一行构建一层镜像,这就是RUN尽可能一个模块写在一起并使用 && 进行连接的原因?

# FROM: 指定基础镜像
FROM centos:7
# MAINTAINER: 指定作者信息
MAINTAINER xiong

# ENV: 设置环境变量
ENV USERNAME root
ENV PASSWORD root

# RUN: 执行shell命令
RUN yum install -y vim
RUN apt-get update && apt-get install -y \
	python
	python-pip
RUN pip install numpy

# ADD: 将宿主机文件复制到容器中
ADD hello.py /tmp/hello.py

# WORKDIR: 指定工作目录
WORKDIR /

# EXPOSE: 暴露端口(谁的端口?)
EXPOSE 5000

# 接收docker run中的输入的字符串作为echo命令的参数, 一般用于制作一些执行后关闭的容器
ENTRYPOINT ["/bin/echo"]
# CMD: 容器启动时执行该命令, 后面是提供echo命令的参数
CMD ["/bin/echo", "Hello, Dockerfile!"]

定义Dockerfile,发布SpringBoot项目(假设为springboot-hello.jar)

  1. 创建一个 Dockerfile 文件,文件名和后缀都任意,假设为 springboot_hello.dockerfile。Dockerfile 文件和 jar 包放到同一个目录下。

    # jar包执行需要JRE环境
    FROM java:8
    ADD springboot-hello.jar ./spring-hello.jar
    CMD java -jar spring-hello.jar
    
  2. 输入 docker build -f <Dockerfile文件路径> -t <镜像名>:<版本号> 命令来构建镜像

    docker build -f springboot_hello.dockerfile -t myHello:1.0
    

保存镜像

容器和镜像不能直接传输,需要将其保存成压缩文件,才能实现镜像的共享。(为什么不直接发布到 docker hub 或私有仓库上,让别人去拉取呢?)

  • 保存镜像:docker save -o <tar文件名> <镜像名>:<版本号>
  • 加载镜像:docker load -i <tar文件名>
  • 保存容器:docker export
  • 加载容器:docker import

保存镜像(先commit,再save)会保留它的历史,保存容器会对它的历史进行压缩,二者类似。

# 将之前创建的redis-demo镜像保存为tar文件. 
docker save -o redis-docker.tar redis-demo:1.0
# 输出路径为当前目录

docker save 保存镜像

Docker 网络

每个容器中只运行一个进程。容器和容器之间通过容器链接或者其它的容器网络技术来进行通信

获取容器的 IP 地址:docker inspect <容器名> | grep "IPAddress"

如果在创建容器时不使用端口映射,相当于在宿主机和容器之间搭建了一个私人网络,在宿主机上可以通过查找容器 IP + 容器端口号来访问容器,但是在其它机器上无法访问容器。

容器链接(过时)

容器链接 docker run --link 在单台主机上可以正常工作,但是在一个大规模系统中,需要使用其它的服务发现方式。可以使用键值存储和 DNS 作为解决方案。另外,Docker Network 提供了一种内建机制来将容器内的服务暴露给外部,而不必使用容器链接。

用户定义网络

默认情况下使用 bridge 网络,但该网络的问题是不能将容器名解析为 IP 地址,例如不可以通过 ping <容器名> 的方式来进行容器间的通信。而用户定义的网络则解决了这个问题。

创建网络:docker network create <网络名>

连接网络:

  • 创建容器时连接到指定网络 docker run --name --network <指定连接的网络名>
  • 运行中容器连接到指定网络 docker network connect <指定连接的网络名> <容器名>

断开网络连接:docker network disconnect <网络名> <容器名>

查看网络信息:docker network inspect <网络名>

从用法上来看,网络和容器的使用方法类似,只是使用 docker network 作为命令的前缀,例如 docker network ls 等等。

Docker Compose 服务编排

服务编排

微服务架构中一般包含多个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启动和停止,维护的工作量会非常大。而服务编排就是按照一定的业务规则批量管理容器,而 Docker Compose 就是进行服务编排的工具之一。Docker Compose 的使用步骤:

  1. 编写 Dockerfile 文件
  2. 使用 docker-compose.yml 文件定义组成应用程序的各个微服务
  3. 运行 docker-compose up 来启动应用程序

Docker Compose 的使用

docker compose 默认被安装,可以通过 docker compose version 查看

使用 docker compose 来编排 nginx + springboot 项目,其中 nginx 能够反向代理多个 springboot 项目生成的容器

  1. 编写 docker-compose.yml 文件

    version: '3'
    services:
      nginx:
        image: nginx
        ports:
          # 短线"-"在yaml文件中的含义表示是数组
          # 这里的80:80是没有空格的, 因为代表的是一个属性值<host_port>:<docker_port>
          - 80:80
        # 需要连接的其它容器, 与其进行通信
        links:
          - app1
          - app2
    
        # 数据卷挂载
        volumes:
          #  nginx的配置文件名叫啥都可以, 以".conf"结尾即可, 推荐为nginx.conf, 在挂载目录中创建即可
          - ./nginx/conf.d:/etc/nginx/conf.d
    
      # springboot-hello是springboot项目生成的一个docker镜像
      # app1 是生成的容器
      app1:
        image: springboot-hello
        expose:
          - "8080"
      app2:
        image: springboot-hello
        expose:
          - "8081"
    
  2. 编写 nginx 的配置文件

    server {
    	listen 80;
    	access_log off;
    	
    	location / {
    		# 配置反向代理
    		proxy_pass http://app1:8080 http://app2:8081;
    	}
    }
    
  3. 使用docker compose up来执行 docker-compose.yml 文件中信息

分布式系统中的容器通信该如何处理,至今未正面面对这个问题。K8S?

通过 Docker 安装其他软件

Docker 安装 MySQL

  1. 拉取 MySQL 的镜像

    docker pull mysql:latest
    

    docker 拉取 mysql 镜像

  2. 查看本地镜像

    docker images
    

    docker 查看本地镜像

  3. 运行容器

    docker run \
    --name mysql-docker \
    -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=root \
    -v /opt/module/data/mysql/data:/var/lib/mysql \
    -v /opt/module/data/mysql/log:/var/log/mysql \
    -v /opt/module/data/mysql/lib:/var/lib/mysql-files \
    -v /opt/module/data/mysql/conf:/etc/mysql \
    -d mysql
    
    参数介绍
    --name mysql-docker指定创建的容器名为 mysql-docker
    -p 3306:3306前一个 3306 是 Linux 宿主机上的端口,后一个 3306 是 mysql-docker 容器中的端口
    -e MYSQL_ROOT_PASSWORD=root设置环境变量 MySQL 的 root 用户的密码为 root
    -v /opt/module/data/mysql/data:/var/lib/mysql指定 MySQL 的数据挂载目录
    -v /opt/module/data/mysql/log:/var/log/mysql
    -v /opt/module/data/mysql/lib/mysql-files:/var/lib/mysql-files
    -v /opt/module/data/mysql/conf:/etc/mysql
    -d mysql:latest指定使用 mysql:latest 这个镜像来启动容器

    -p <宿主机的port>:<容器的port>:实现容器端口到宿主机端口的映射。外部机器不可以与宿主机的容器直接通信, 宿主机可以与容器直接通信, 外部机可以与宿主机直接通信。通过端口映射,例如宿主机的3307对应着访问容器的3306,当外部机器需要访问容器的3306端口时,访问宿主机的3307端口即可

  4. 使用 docker ps 来查看正在运行中的容器(取名为 mysql-docker)

    查看 mysql-docker 是否成功启动

  5. 在宿主机上修改 MySQL 的配置 vim /opt/module/data/mysql/conf/my.cnf

    # 防止中文乱码
    [client]
    default-character-set=utf8
    
    [mysql]
    default-character-set=utf8
    
    [mysqld]
    init_connect='SET collation_connection = utf8_unicode_ci'
    init_connect='SET NAMES utf8'
    character-set-server=utf8
    collation-server=utf8_unicode_ci
    skip-character-set-client-handshake
    skip-name-resolve
    #################################### 集群配置 ###################################
    # mysql集群中的id, 集群下需要唯一
    server_id=101
    # 指定不需要同步的数据库名称
    binlog-ignore-db=mysql
    # 开启二进制日志功能
    log-bin=mall-mysql-bin
    # 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M
    # 设置mysql集群使用的binlog日志的格式(mixed,statement,row)
    binlog_format=mixed
    expire_logs_days=7
    slave_skip_errors=1062
    ############################ MySQL从服务器需要额外配置下面参数 ##########################
    # relay_log 配置中继日志
    relay_log=mall-mysql-relay-bin
    # log_slave_updates表示slave将复制事件写入自己的binlog日志中
    log_slave_updates=1
    # slave设置为只读
    read_only=1
    
  6. 重启 mysql-docker 来应用更新后的配置

    docker restart mysql-docker
    
  7. 使用 docker exec -it mysql-docker 进入到 mysql-docker 容器中,成功进入代表部署成功

    进入正在运行中的docker容器
  8. 使用 whereis mysql 命令来查看 MySQL 的安装位置

    查看 MySQL 的安装位置
  9. 使用 cat /etc/mysql/my.cnf 来查看在宿主机上修改的配置文件

  10. 使用 mysql -uroot -proot 来进入 MySQL,在其中创建一个数据库,方便后面的测试连接

  11. 在 IDEA 中进行外部的连接测试

    通过 IDEA 进行外部连接测试
  12. (主从复制)MySQL 主服务器中开启主从复制

    这部分感觉可以不用进行配置?直接把root用户给SLAVE服务器?

    CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
    GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
    
  13. (主从复制)在主服务器上获取一些用于主从复制的信息

    SHOW MASTER STATUS;
    
  14. (主从复制)在从服务器中指定主服务器

    CHANGE MASTER TO 
    MASTER_HOST='<mysql主服务器的ip地址>',
    MASTER_USER='root',
    MASTER_PASSWORD='root',
    MASTER_PORT=3306,
    MASTER_LOG_FILE='mall-mysql-bin.000001',
    MASTER_LOG_POS=617,
    MASTER_CONNECT_RETRY=30;
    

    上面的信息需要根据 MySQL主服务器上情况进行修改

  15. (主从复制)在 MySQL 从服务器中开启主从复制

    START SLAVE;
    
  16. (主从复制)主从复制配置成功的测试

    
    

Docker 安装 Redis

  1. 创建并启动 Redis

    docker run \
    -p 6379:6379 \
    --name redis-docker \
    -v /opt/module/data/redis/data:/data \
    -v /opt/module/data/redis/conf/:/etc/redis/conf \
    -d redis \
    redis-server /etc/redis/conf/redis.conf
    

    最后一行的 redis-server /etc/redis/redis.conf 实际上是 redis 启动服务端的命令,难道说 docker run 可以直接执行 sh 命令吗?那是否可以写上 mysql -uroot -proot 来直接登录 MySQL 呢?

    redis-server /etc/redis/conf/redis.conf 是指定redis-docker容器启动时使用的配置文件,由于上面没有创建 redis.conf 文件,所以实际上并没有成功启动。可以通过 docker logs -f redis-docker 查看日志,能够看到 Fatal error, can’t open config file ‘/etc/redis/conf/redis.conf’: No such file or directory 这样的错误。

  2. 在宿主机的挂载目录 /opt/module/data/redis/conf 中创建 redis.conf 文件,并设置允许远程访问 Redis

    挂载目录实际上就是容器内的目录,相当于创建了一个快捷方式(软链接),对挂载目录中的操作实际上是对容器内部的目录进行操作。

    bind 0.0.0.0
    protected-mode no
    
  3. 使用 docker start redis-docker 来真正启动Redis容器

  4. 使用 redis-docker 容器来执行连接 Redis

    docker exec -it redis-docker redis-cli
    

    这里标明不需要进入到容器中再去执行 redis-cli 命令,做了一点点简化。

Docker 安装 Redis 集群

配置一个 3 主 3 从的 Redis 集群

  1. 创建一个用户自定义网络,不妨命名为 redis-network

    docker network create redis-network
    
  2. 下面的配置文件复制 6 份,启动 6 个 Redis 容器
    (redis-master-6380、redis-master-6381、redis-master-6382、redis-slave-6383、redis-slave-6384、redis-slave-6385)

    docker run \
    -p 6380:6379 \
    --name redis-master-6380 \
    --network redis-network
    --privileged=true \
    -v /opt/module/data/redis/data:/data \
    -v /opt/module/data/redis/conf/:/etc/redis/conf \
    --cluster-enabled yes \
    --appendonly yes \
    -d redis \
    redis-server /etc/redis/conf/redis.conf
    
  3. 将多个 Redis 节点合并成一个 Redis 集群(不指定 master 和 slave)

    redis-cli --cluster create \
    <ip1>:<port1> \
    <ip2>:<port2> \
    <ip3>:<port3> \
    <ip4>:<port4> \
    <ip5>:<port5> \
    <ip6>:<port6> \
    --cluster-replicas 1 \
    --cluster-yes
    
  4. 为 master 节点添加 slave 节点

    其中 <node-id> 通过 redis-cli cluster nodes 来获取

    redis-cli \
    -h <ip1> -p <port1> \
    cluster replicate <node-id>
    

Docker 安装 Nginx

  1. 创建并启动 Nginx

    docker run \
    -p 8000:80 \
    --name nginx-docker \
    -v /opt/module/data/nginx/conf:/etc/nginx/conf \
    -v /opt/module/data/nginx/log:/var/log/nginx \
    -d nginx
    

安装过程中的错误记录

使用 docker ps 查看正在运行的容器

使用 docker logs mysql-docker 来查看容器报错日志

可能存在的问题:

  • 如果这里并没有 mysql 容器在运行,那么有可能是因为端口冲突,或者一些其它别的问题?(换一台主机测试成功)
  • 可能一开始能够通过 docker ps 查看到运行中的 mysql-docker,但是隔一段时间后发现 mysql-docker 停止了,这也说明 mysql-docker 并没有成功运行。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值