docker镜像操作实操

C++Hello world镜像制作

  • 创建目录,在目录下创建c++源代码demo.c
bash 复制代码
mkdir 目录
cd 目录
vim demo.c
  • 创建Dockerfile
bash 复制代码
#指定基础镜像
FROM centos:7
#设置版本
ENV VWESION=1.0
#替换国内源
RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-Base.repo && \
    sed -i 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.aliyun.com/centos-vault/centos|g' /etc/yum.repos.d/CentOS-Base.repo && \
    yum clean all && yum makecache
#设置工作目录
WORKDIR /src
#拷贝源文件
COPY demo.c .
#安装gcc
RUN yum makecache && yum install gcc -y
#编译源文件
RUN gcc demo.c -o demo && \
	rm -f demo.c && \
	yum remove -y gcc
#运行可执行文件
CMD ["/src/demo"] 
  • 执行构建,运行镜像查看结果
bash 复制代码
docker build -t cpp:v0.1 .
docker run --name test1 --rm cpp:v0.1

CMD和ENTRYPOINT

这两个指令都是在docker image中执行一条命令,但它们之间有区别。

执行一个没有调用ENTRYPOINT或者CMD的docker镜像会返回错误,一般的镜像最后都提供了CMD或者ENTRYPOINT作为入口。

操作

覆盖

在写dockerfile时,ENTRYPOINT或者CMD命令会自动覆盖之前的ENTRYPOINT或者CMD命令,用户也可以在命令中指定具体命令,如果不希望docker镜像执行的具体程序被用户执行docker run覆盖,可以使用ENTRYPOINT。
多次覆盖

  • 创建一个Dockerfile,指定多个CMD
bash 复制代码
FROM busybox
CMD echo "hello world"
CMD echo "hello vientiane"
  • 编译运行,可以看到第一个CMD被覆盖了

    参数覆盖
  • 在docker run的时候指定后面的启动参数
bash 复制代码
FROM busybox
CMD echo "hello world"
CMD echo "hello vientiane"
bash 复制代码
docker run --name test1 --rm cpp:v0.2 echo "hello CMD"
  • 但如果是ENTRYPOINT的话,那无法覆盖,除非指定参数--entrypoint

Shell和Exec

  • 编写Dockerfile,执行ping命令
bash 复制代码
FROM ubuntu:22.04
RUN apt-get update -y && apt install -y iputils-ping
CMD ping localhost
  • 编译镜像,进入镜像里面查看,可以看到pid为1的是/bin/sh

  • 但如果使用exec模式,可以看到pid为1的进程是ping而不是/bin/sh

组合

  • 新建dockerfile,同时设置ENTRYPOINT和CMD
bash 复制代码
FROM ubuntu:22.04
RUN apt-get update -y && apt install -y iputils-ping
ENTRYPOINT ["/bin/ping","-c","3"]
CMD ["localhost"] 
  • 编译镜像后启动运行,可以看到CMD的内容作为ENTRYPOINT的参数添加到了后面
bash 复制代码
docker build -t cpp:v0.4 .
docker run --name test1 --rm cpp:v0.4
  • 因为CMD的内容可以更换,如果我们运行的时候替换成另外一个网址,我们就可以看到它ping的是另外一个网址
bash 复制代码
docker run --name test1 --rm cpp:v0.4 www.baidu.com

dockerignore

docker是C-S架构,理论上Client和Server可以不在一台机器上,在构建docker镜像的时候,需要把文件从Client发送给Server,这些要发送的文件成为欸build context。

bash 复制代码
docker build -f <dockerfile> -t <dockerfilename> .

如果想要忽略掉一些传输给server短的文件,就会用到.dockerignore文件,它会将有记录的所有文件都忽略掉,不会传输给server端。

操作

  • 建立dockerfile
bash 复制代码
FROM centos:7
COPY ./* /
  • 建立.dockerignore文件,忽略以txt为后缀的文件,在文件里输入*.txt
bash 复制代码
cat .dockerignore
  • 制造一些文件
bash 复制代码
touch 1.txt 2.txt 3.doc 4.rtf
  • 构建镜像并查看结果
bash 复制代码
docker build -f ./dockerfile -t cpp:v0.6 .
docker run -it cpp:v0.6

多阶段构建

构建docker镜像有两种方式,第一种是将全部组件及其依赖库的编译,测试,打包流程都封装仅一个docker镜像中,第二种是将每个阶段分散到多个dockerfile。
单文件构建

  • 创建目录,在目录下创建c++源代码demo.c
bash 复制代码
mkdir 目录
cd 目录
vim demo.c
  • 创建Dockerfile
bash 复制代码
#指定基础镜像
FROM centos:7
#设置版本
ENV VWESION=1.0
#替换国内源
RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-Base.repo && \
    sed -i 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.aliyun.com/centos-vault/centos|g' /etc/yum.repos.d/CentOS-Base.repo && \
    yum clean all && yum makecache
#设置工作目录
WORKDIR /src
#拷贝源文件
COPY demo.c .
#安装gcc
RUN yum makecache && yum install gcc -y
#编译源文件
RUN gcc demo.c -o demo && \
	rm -f demo.c && \
	yum remove -y gcc
#运行可执行文件
CMD ["/src/demo"] 
  • 执行构建,运行镜像查看结果,可以看到生成的镜像很大
bash 复制代码
docker build -t cpp:v0.1 .
docker run --name test1 --rm cpp:v0.8
docker image ls | grep cpp


多阶段构建

实际上我们把test.c编译完之后,并不需要一个大的gcc编译环境,只需要一个小的运行环境镜像即可。

  • 创建目录,在目录下创建c++源代码demo.c
bash 复制代码
mkdir 目录
cd 目录
vim demo.c
  • 创建Dockerfile
bash 复制代码
#第一阶段构建
#指定基础镜像
FROM centos:7 as base
#设置版本
ENV VWESION=1.0
#替换国内源
RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-Base.repo && \
    sed -i 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.aliyun.com/centos-vault/centos|g' /etc/yum.repos.d/CentOS-Base.repo && \
    yum clean all && yum makecache
#设置工作目录
WORKDIR /src
#拷贝源文件
COPY demo.c .
#安装gcc
RUN yum makecache && yum install gcc -y
#编译源文件
RUN gcc demo.c -o demo && \
	rm -f demo.c && \
	yum remove -y gcc
#运行可执行文件
CMD ["/src/demo"] 

#第二阶段构建
FROM centos:7
#拷贝第一阶段生成的可执行程序
COPY --from=base /src/demo /src/demo
#运行可执行程序
CMD ["/src/demo"]
  • 执行构建,运行镜像查看结果,可以看到生成的镜像变小了很多
bash 复制代码
docker build -t cpp:v0.9 .
docker run --name test1 --rm cpp:v0.9
docker image ls | grep cpp
  • 当我们使用busybox这一类更小的镜像的时候,会发现构建完之后的镜像更小了
  • 创建Dockerfile
bash 复制代码
#第一阶段构建
#指定基础镜像
FROM centos:7 as base
#设置版本
ENV VWESION=1.0
#替换国内源
RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-Base.repo && \
    sed -i 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.aliyun.com/centos-vault/centos|g' /etc/yum.repos.d/CentOS-Base.repo && \
    yum clean all && yum makecache
#设置工作目录
WORKDIR /src
#拷贝源文件
COPY demo.c .
#安装gcc
RUN yum makecache && yum install gcc -y
#编译源文件
RUN gcc demo.c -o demo && \
	rm -f demo.c && \
	yum remove -y gcc
#运行可执行文件
CMD ["/src/demo"] 

#第二阶段构建
FROM busybox
#拷贝第一阶段生成的可执行程序
COPY --from=base /src/demo /src/demo
#运行可执行程序
CMD ["/src/demo"]
  • 执行构建,运行镜像查看结果,可以看到生成的镜像只有几MB
bash 复制代码
docker build -t cpp:v0.1 .
docker run --name test1 --rm cpp:v1.0
docker image ls | grep cpp

使用缓存

在镜像构建过程中,docker会根据dockerfile指定的顺序执行每一个指令,在执行每一条指令之前,docker都会在缓存中查找是否存在可重用的镜像,如果有就使用现存的镜像,不会重复创建。

如果在构建的时候不想使用缓存,可以在docker build中使用--no-cache=true。

操作

  • 改变源代码文件demo.c重新构建镜像,这里也并没有使用到缓存,所以也需要构建很久。要怎么避免这种情况呢?
bash 复制代码
#第一阶段构建
#指定基础镜像
FROM centos:7 as base
#设置版本
ENV VWESION=1.0
#替换国内源
RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-Base.repo && \
    sed -i 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.aliyun.com/centos-vault/centos|g' /etc/yum.repos.d/CentOS-Base.repo && \
    yum clean all && yum makecache
#设置工作目录
WORKDIR /src
#拷贝源文件
COPY demo.c .
#安装gcc
RUN yum makecache && yum install gcc -y
#编译源文件
RUN gcc demo.c -o demo && \
	rm -f demo.c && \
	yum remove -y gcc
#运行可执行文件
CMD ["/src/demo"] 

#第二阶段构建
FROM busybox
#拷贝第一阶段生成的可执行程序
COPY --from=base /src/demo /src/demo
#运行可执行程序
CMD ["/src/demo"]
  • 可以将不经常修改的内容调节到dockerfile前边,经常修改的内容放在dockerfile文件后面(这里将COPY往后挪了),这样就可以尽量多的复用缓存了。
bash 复制代码
#第一阶段构建
#指定基础镜像
FROM centos:7 as base
#设置版本
ENV VWESION=1.0
#替换国内源
RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-Base.repo && \
    sed -i 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.aliyun.com/centos-vault/centos|g' /etc/yum.repos.d/CentOS-Base.repo && \
    yum clean all && yum makecache
#设置工作目录
WORKDIR /src
#安装gcc
RUN yum makecache && yum install gcc -y
#拷贝源文件
COPY demo.c .
#编译源文件
RUN gcc demo.c -o demo && \
	rm -f demo.c && \
	yum remove -y gcc
#运行可执行文件
CMD ["/src/demo"] 

#第二阶段构建
FROM busybox
#拷贝第一阶段生成的可执行程序
COPY --from=base /src/demo /src/demo
#运行可执行程序
CMD ["/src/demo"]

这里仅用了1.7s

搭建MySQL主从同步

在docker-compose.yml文件中可以使用build选项来编译镜像。

bash 复制代码
service:
#格式1,指定的上下文目录是./web,在构建的时候会自动在此目录下寻找Dockerfile,构建完后,镜像命名为test/web
	frontend:
		image: test/web
		build: ./web
#格式2,指定的上下文目录是./database,在构建的时候会自动在此目录下寻找backend.dockerfile,构建完后,镜像命名为test/database
	backend:
		image:test/database
		build:
			context: ./database
			dockerfile: ./backend.dockerfile

编辑完后,就使用docker compose build来构建所有服务的镜像。

操作

创建一个一主二从的MySQL集群

  • 创建目录
bash 复制代码
mkdir -p ./mysqlcluster
mkdir -p ./mysqlcluster/master
mkdir -p ./mysqlcluster/slave
  • 进入./mysqlcluster/master,创建主dockerfile文件名为Dockerfile-master,配置系统时区为上海
bash 复制代码
FROM mysql:5.7.36
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  • 进入./mysqlcluster/slave,创建从dockerfile,文件名为Dockerfile-slave,配置系统时区为上海
bash 复制代码
FROM mysql:5.7.36
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY ./slave/slave.sql /docker-entrypoint-initdb.d
  • 创建从库配置脚本slave.sql
bash 复制代码
change master to master_host='mysql-master'
master_user='root',master_password='root',master_port=3306;
start slave;
  • 进入./mysqlcluster目录,创建docker-compose.yml配置文件
bash 复制代码
version: "3"

services:
  # MySQL 主节点
  mysql-master:
    build:
      context: ./
      dockerfile: ./master/Dockerfile-master
    image: mysqlmaster:v1.0
    restart: always
    container_name: mysql-master
    volumes:
      - ./mastervarlib:/var/lib/mysql
    ports:
      - 9306:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
    privileged: true
    command: 
      - '--server-id=1'
      - '--log-bin=master-bin'
      - '--binlog-ignore-db=mysql'
      - '--binlog_cache_size=256M'
      - '--binlog_format=mixed'
      - '--lower_case_table_names=1'
      - '--character-set-server=utf8'
      - '--collation-server=utf8_general_ci'

  # MySQL 从节点1
  mysql-slave:
    build:
      context: ./
      dockerfile: ./slave/Dockerfile-slave
    image: mysqlslave:v1.0
    restart: always
    container_name: mysql-slave
    volumes:
      - ./slavevarlib:/var/lib/mysql
    ports:
      - 9307:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
    privileged: true
    command: 
      - '--server-id=2'
      - '--relay_log=slave-relay'
      - '--lower_case_table_names=1'
      - '--character-set-server=utf8'
      - '--collation-server=utf8_general_ci'
    depends_on:
      - mysql-master

  # MySQL 从节点2
  mysql-slave2:
    build:
      context: ./
      dockerfile: ./slave/Dockerfile-slave
    image: mysqlslave:v1.0
    restart: always
    container_name: mysql-slave2
    volumes:
      - ./slavevarlib2:/var/lib/mysql
    ports:
      - 9308:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
    privileged: true
    command: 
      - '--server-id=3'
      - '--relay_log=slave-relay'
      - '--lower_case_table_names=1'
      - '--character-set-server=utf8'
      - '--collation-server=utf8_general_ci'
    depends_on:
      - mysql-master
  • 构建镜像
bash 复制代码
docker compose build
  • 启动服务进行测试
bash 复制代码
docker compose up
  • 查看状态
bash 复制代码
docker compose ps
  • 连接主库,查看数据库可以看到运行正常
bash 复制代码
docker exec -it mysql-master bash
  • 查看数据库角色和同步状态
bash 复制代码
show master status\G
  • 在主库上创建数据库,连接上任意一个从库,查从库数据库
相关推荐
用户0328472220703 小时前
如何搭建本地yum源(上)
运维
武子康4 小时前
调查研究-183 Apple container:Mac 上用轻量 VM 跑 Linux 容器,Swift 会改写本地容器体验吗?
docker·容器·apple
大树883 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工3 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
Alsn863 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
酣大智3 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_3 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉3 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造