目录
一 Docker简介及部署方法
1.1 Docker简介
2008 年LXC(LinuX Contiainer)发布,但是没有行业标准,兼容性非常差 docker2013年首次发布,由Docker, Inc开发
1.1.1 什么是docker?
Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术
它具有以下几个重要特点和优势:
1. 轻量级虚拟化 :
Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。
例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。
2. 一致性 :
确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。 无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。
3. 可移植性 :
可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差 异。 比如,在本地开发的容器可以无缝部署到云服务器上。
4. 高效的资源利用:
多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资 源。
5. 易于部署和扩展:
能够快速部署新的应用实例,并且可以根据需求轻松地进行水平扩展。 总之,Docker 极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。 它在现代软件开发和云计算领域得到了广泛的应用。
1.1.2 docker在企业中的应用场景
- 在企业中docker作为业务的最小载体而被广泛应用
- 通过docker企业可以更效率的部署应用并更节省资源
注意!!!!:
IaaS(Infrastructure as a Service),即基础设施即服务
PaaS是(Platform as a Service)即指平台即服务
SaaS(Software as a Service)软件运营服务是
1.1.3 docker与虚拟化的对比
虚拟机 | docker容器 | |
操作系统 | 宿主机上运行虚拟机OS | 共享宿主机OS |
存储 | 镜像较大(GB | 镜像小(MB) |
性能 | 操作系统额外的cpu、内存消耗 | 几乎无性能损耗 |
移植性 | 笨重、与虚拟化技术耦合度高 | 轻量、灵活迁移 |
隔离性 | 完全隔离 | 安全隔离 |
部署 | 慢、分钟级 | 快速、秒级 |
运行密度 | 一般几十个 | 单机支持上千容器 |
1.1.4 docker的优势
- 对于开发人员:Build once、Run anywhere。
- 对于运维人员:Configure once、Run anything
- 容器技术大大提升了IT人员的幸福指数!
2 部署docker
2.1 容器工作方法
2.2 部署第一个容器
官方站点: https://docs.docker.com/
实验准备:
主机名 | IP |
docker-node1 | 172.25.254.100 |
由于无法拉取镜像,这个博客所以的实验用到的镜像都是提前从压缩包里准备好了的
2.2.1 配置软件仓库
[root@docker-node1 ~]# cd /etc/yum.repos.d
[root@docker-node1 yum.repos.d]# vim docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker
ce/linux/centos/7/x86_64/stable/
gpgcheck=0
[centos]
name=extras
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64
gpgcheck=0
2.2.2 安装docker-ce并启动服务
#安装docker
[root@docker-node1 ~]# yum install -y docker-ce
#编辑docker启动文件,设定其使用iptables的网络设定方式,默认使用nftables
[root@docker-node1 ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
[root@docker-node1 ~]# systemctl enable --now docker
[root@docker-node1 ~]# docker info
2.2.3 激活内核网络选项
#在rhel7中 需要
[root@docker-node1 ~]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
[root@docker-node1 ~]# sysctl --system
[root@docker-node1 ~]# systemctl restart docker
2.3 通过压缩包安装
#解压压缩包,并安装rpm包
[root@docker-node1 ~]# tar zxf docker.tar.gz
[root@docker-node1 ~]# yum install *.rpm -y
#启动docker
[root@docker-node1 ~]# systemctl enable --now docker
[root@docker-node1 ~]# systemctl restart docker
[root@docker-node1 ~]# docker info
#将压缩包加载到本地的 Docker 环境中以供使用。
[root@docker-node1 ~]# docker load -i game2048.tar.gz
[root@docker-node1 ~]# docker load -i mario.tar.gz
[root@docker-node1 ~]# docker load -i nginx-latest.tar.gz
[root@docker-node1 ~]# docker load -i busybox-latest.tar.gz
#查看是否加载成功
[root@docker-node1 ~]# docker images
#运行测试是否成功
[root@docker-node1 ~]# docker run -d --rm --name webserver -p 80:80 nginx
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dce64a796306 nginx "/docker-entrypoint.…" 22 seconds ago Up 22 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp webserver
[root@docker-node1 ~]# docker rm -f webserver
webserver
[root@docker-node1 ~]# docker ps
三 Docker的基本操作
3.1 Docker镜像管理
3.1.1 搜索镜像
四 docker镜像构建
4.1 docker镜像结构
- 共享宿主机的kernel
- base镜像提供的是最小的Linux发行版
- 同一docker主机支持运行多种Linux发行版
- 采用分层结构的最大好处是:共享资源
4.2 镜像运行的基本原理
- Copy-on-Write 可写容器层
- 容器层以下所有镜像层都是只读的
- docker从上往下依次查找文件
- 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
- 一个镜像最多127层
4.3 镜像获得方式
- 基本镜像通常由软件官方提供
- 企业镜像可以用官方镜像+Dockerfile来生成
- 系统关于镜像的获取动作有两种:
- docker pull 镜像地址
- docker load –i 本地镜像包
4.4 镜像构建
4.4.1 构建参数
参数 | 意思 |
FROM | 指定base镜像 eg:FROM busybox:version |
COPY | 复制文件 eg:COPY file /file 或者 COPY [“file”,”/”] |
MAINTAINER | 指定作者信息,比如邮箱 eg:MAINTAINER user@example.com 在最新版的docker中用LABEL KEY="VALUE"代替 |
ADD | 功能和copy相似,指定压缩文件或url eg: ADD test.tar /mnt 或者 eg:ADD http://ip/test.tar /mnt |
ENV | 指定环境变量 eg:ENV FILENAME test |
EXPOSE | 暴漏容器端口 eg:EXPOSE 80 |
VOLUME | 申明数据卷,通常指数据挂载点 eg:VOLUME [“/var/www/html”] |
WORKDIR | 切换路径 eg:WORKDIR /mnt |
RUN | 在容器中运行的指令 eg: touch file |
CMD | 在启动容器时自动运行动作可以被覆盖 eg:CMD echo $FILENAME 会调用 shell解析 eg:CMD [“/bin/sh”,”-c”,“echo $FILENAME”] 不调用shell解析 |
ENTRYPOINT | 和CMD功能和用法类似,但动作不可被覆盖 |
参数示例及用法
#FROM COPY 和MAINTAINER
[root@Docker-node1 ~]# mkdir docker/
[root@Docker-node1 ~]# cd docker/
[root@Docker-node1 docker]# touch leefile
[root@Docker-node1 docker]# vim Dockerfile
FROM busybox:latest #指定使用的基础镜像
MAINTAINER admin@test.org #指定作者信息
COPY testfile / #复制当前目录文件到容器指定位置,testfile必须在当前目录中
[root@Docker-node1 docker]# docker build -t example:v1 .
#ADD
[root@Docker-node1 docker]# touch leefile{1..3}
[root@Docker-node1 docker]# tar zcf leefile.gz leefile*
[root@Docker-node1 docker]# vim Dockerfile
FROM busybox
MAINTAINER admin@test.org
COPY leefile /
ADD leefile.gz /
[root@Docker-node1 docker]# docker build -t example:v2 .
[root@Docker-node1 docker]# docker run -it --rm --name test example:v2
/ # ls
#ENV CMD
FROM busybox
MAINTAINER admin@test.org
ENV NAME test
CMD echo $NAME
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3
test
FROM busybox
MAINTAINER admin@test.org
ENV NAME test
CMD ["/bin/echo", "$NAME"]
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3
$NAME
#ENV CMD
FROM busybox
MAINTAINER admin@test.org
ENV NAME test
CMD ["/bin/sh", "-c", "/bin/echo $NAME"]
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3
test
#ENTRYPOINT
FROM busybox
MAINTAINER admin@test.org
ENV NAME test
ENTRYPOINT echo $NAME
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3 sh
test
#EXPOSE VOLUME VOLUME
FROM busybox
MAINTAINER admin@test.org
ENV NAME test
EXPOSE 80 443
VOLUME /var/www/html
WORKDIR /var/www/html
RUN touch leefile
[root@Docker-node1 docker]# docker build -t example:v4 .
[root@Docker-node1 docker]# docker run -it --rm --name test example:v4
/var/www/html #
4.4.2 Dockerfile实例
建立centos7
准备工作:虚拟机需要两个CD/DVD,一个是rhel9.4,另外一个是rhel7.9
#将centos7加载到本地的 Docker 环境中以供使用
[root@docker-node2 ~]# docker load -i /mnt/centos-7.tar.gz
174f56854903: Loading layer 211.7MB/211.7MB
Loaded image: centos:7
[root@docker-node2 ~]# cd docker/
[root@docker-node2 docker]# mv /mnt/nginx-1.26.1.tar.gz .
[root@docker-node2 docker]# ls
Dockerfile nginx-1.26.1.tar.gz
#配置文件
[root@docker-node1 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=admin@test.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y
RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]
[root@docker-node2 docker]# docker build -t webserver:v1 .
#配置HTTP和挂载
[root@docker-node1 docker]# yum install httpd -y
[root@docker-node1 docker]# vim /etc/httpd/conf/httpd.conf
[root@docker-node1 docker]# systemctl restart httpd
[root@docker-node1 docker]# mkdir /var/www/html/rhel7.9
[root@docker-node1 docker]# mount /dev/sr1 /var/www/html/rhel7.9/
mount: /var/www/html/rhel7.9: WARNING: source write-protected, mounted read-only.
#查看容器的网络(一定要启动容器才能看到网络)
[root@docker-node1 docker]# docker run -it --name centos centos:7
[root@7d4c2668f09e /]#
[root@docker-node1 docker]# docker inspect centos
#配置仓库
[root@docker-node1 docker]# docker run -it --name centos centos:7
[root@34b2ac427894 /]# cd /etc/yum.repos.d/
[root@34b2ac427894 yum.repos.d]# rm -rf *
[root@34b2ac427894 yum.repos.d]# vi centos7.repo
[centos7]
name=centos7
baseurl=http://172.17.0.1:8888/rhel7.9
gpgcheck=0
[root@docker-node1 yum.repos.d]# docker commit -m "add repo" centos centos:repo
sha256:3e761d58fcc47abfa2a55eaab9d0be9ba22a0e734063f99d4491b0d198f45e97
[root@docker-node1 yum.repos.d]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos repo 3e761d58fcc4 4 seconds ago 204MB
nginx latest 5ef79149e0ec 12 days ago 188MB
busybox latest 65ad0d468eb1 15 months ago 4.26MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
timinglee/game2048 latest 19299002fdbe 7 years ago 55.5MB
timinglee/mario latest 9a35a9e43e8c 8 years ago 198MB
[root@65b4c98291a5 yum.repos.d]# exit
exit
[root@docker-node1 docker]# docker rm centos
centos
[root@docker-node1 docker]# docker build -t webserver:v1 .
[+] Building 28.6s (12/12) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 414B 0.0s
=> [internal] load metadata for docker.io/library/centos:repo 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 1.25MB 0.0s
=> [1/7] FROM docker.io/library/centos:repo 0.0s
=> [2/7] ADD nginx-1.26.1.tar.gz /mnt 0.2s
=> [3/7] WORKDIR /mnt/nginx-1.26.1 0.0s
=> [4/7] RUN yum install gcc make pcre-devel openssl-devel -y 4.4s
=> [5/7] RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with 5.0s
=> [6/7] RUN make 18.3s
=> [7/7] RUN make install 0.2s
=> exporting to image 0.4s
=> => exporting layers 0.4s
=> => writing image sha256:5d2d60fd89872faf40a66c168ff9b3c990d3dd0b9fa30c75f84f4 0.0s
=> => naming to docker.io/library/webserver:v1 0.0s
4.5 镜像优化方案
4.5.1 镜像优化策略
- 选择最精简的基础镜像
- 减少镜像的层数
- 清理镜像构建的中间产物
- 选择最精简的基础镜像
- 减少镜像的层数
- 清理镜像构建的中间产物
4.5.2 镜像优化示例
4.5.2.1 方法1.缩减镜像层
[root@node1 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=admin@test.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make && make install && rm -rf /mnt/nginx.1.26.1 && yum clean all
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]
[root@node1 docker]# docker build -t webserver:v1 .
[root@node1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v3 cc71beda411e 13 minutes ago 34.5MB
webserver v2 43eba985f5db 42 minutes ago 210MB
webserver v1 b3309248e2bf 47 minutes ago 313MB
<none> <none> f2afa136ea2d 52 minutes ago 356MB
centos repo a732bd43ba9b 53 minutes ago 204MB
nginx latest 5ef79149e0ec 2 weeks ago 188MB
nginx 1.23 a7be6198544f 15 months ago 142MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
gcr.io/distroless/base-debian11 latest 2a6de77407bf N/A 20.6MB
4.5.2.2 方法2.多阶段构建
[root@node1 docker]# vim Dockerfile
FROM centos:repo AS build
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make && make install && rm -rf /mnt/nginx.1.26.1 && yum clean all
FROM centos:repo
LABEL Mail=admin@test.com
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
[root@node1 docker]# docker build -t webserver:v2 .
[root@node1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v2 43eba985f5db 3 minutes ago 210MB
webserver v1 f2afa136ea2d 13 minutes ago 356MB
centos repo a732bd43ba9b 14 minutes ago 204MB
nginx latest 5ef79149e0ec 2 weeks ago 188MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
4.5.2.3 方法3.使用最精简镜像
使用google提供的最精简镜像
下载地址: https://github.com/GoogleContainerTools/distroless
下载镜像: docker pull gcr.io/distroless/base
[root@node1 docker]# vim Dockerfile
FROM nginx:1.23 AS base
ARG TIME_ZONE
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
cp -a --parents /usr/share/nginx /opt && \
cp -a --parents /var/log/nginx /opt && \
cp -aL --parents /var/run /opt && \
cp -a --parents /etc/nginx /opt && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/sbin/nginx /opt && \
cp -a --parents /usr/sbin/nginx-debug /opt && \
cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
FROM gcr.io/distroless/base-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@node1 docker]# docker build -t webserver:v3 .
[root@node1 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v3 cc71beda411e About a minute ago 34.5MB
webserver v2 43eba985f5db 30 minutes ago 210MB
webserver v1 f2afa136ea2d 40 minutes ago 356MB
centos repo a732bd43ba9b 41 minutes ago 204MB
nginx latest 5ef79149e0ec 2 weeks ago 188MB
nginx 1.23 a7be6198544f 15 months ago 142MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
gcr.io/distroless/base-debian11 latest 2a6de77407bf N/A 20.6MB
五 docker 镜像仓库的管理
5.1 什么是docker仓库
Docker 仓库(Docker Registry) 是用于存储和分发 Docker 镜像的集中式存储库。
它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉 取所需的镜像。
Docker 仓库可以分为公共仓库和私有仓库:
- 公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在 Docker Hub 上提供的镜像,方便用户直接获取和使用。 例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。
- 私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。 比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中, 以保证安全性和控制访问权限。
通过 Docker 仓库,开发者能够方便地共享和复用镜像,加速应用的开发和部署过程。
5.2 docker hub
官网: https://hub.docker.com/
Docker Hub 是 Docker 官方提供的一个公共的镜像仓库服务。
它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,拥有大量的官方和社区贡献的镜像。
以下是 Docker Hub 的一些关键特点和优势:
1. 丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用 的镜像。
- 例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库 的镜像。
2. 官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。
3. 社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。
4. 版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。
5. 便于搜索:用户可以通过关键词轻松搜索到所需的镜像。
5.2.1 docker hub的使用方法
#登陆官方仓库
[root@docker ~]# docker login
Log in with your Docker ID or email address to push and pull images from Docker
Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to
create one.
You can log in with your password or a Personal Access Token (PAT). Using a
limited-scope PAT grants better security and is required for organizations using
SSO. Learn more at https://docs.docker.com/go/access-tokens/
Username: timinglee
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
#登陆信息保存位置
[root@docker ~]# cd .docker/
[root@docker .docker]# ls
config.json
[root@docker .docker]# cat config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "dGltaW5nbGVlOjY3NTE1MTVtaW5nemxu"
}
}
[root@docker ~]# docker tag gcr.io/distroless/base-debian11:latest
timinglee/base-debian11:latest
[root@docker ~]# docker push timinglee/base-debian11:latest
The push refers to repository [docker.io/timinglee/base-debian11]
6835249f577a: Pushed
24aacbf97031: Pushed
8451c71f8c1e: Pushed
2388d21e8e2b: Pushed
c048279a7d9f: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
bbb6cacb8c82: Pushed
ac805962e479: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
9ed498e122b2: Pushed
577c8ee06f39: Pushed
5342a2647e87: Pushed
latest: digest:
sha256:f8179c20f1f2b1168665003412197549bd4faab5ccc1b140c666f9b8aa958042 size:
3234
5.3 docker仓库的工作原理
仓库中的三个角色
index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证
Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。
5.3.1 pull原理
镜像拉取分为以下几步:
1.docker客户端向index发送镜像拉去请求并完成与index的认证
2.index发送认证token和镜像位置给dockerclient
3.dockerclient携带token和根据index指引的镜像位置取连接registry
4.Registry会根据client持有的token跟index核实身份合法性
5.index确认此token合法性 6.Registry会根据client的请求传递镜像到客户端
5.3.2 push原理
镜像上传的步骤:
1.client向index发送上传请求并完成用户认证
2.index会发方token给client来证明client的合法性
3.client携带index提供的token连接Registry
4.Registry向index合适token的合法性
5.index证实token的合法性
6.Registry开始接收客户端上传过来的镜像
5.3 搭建docker的私有仓库
5.3.1 为什么搭建私有仓库
docker hub虽然方便,但是还是有限制
- 需要internet连接,速度慢
- 所有人都可以访问
- 由于安全原因企业不允许将镜像放到外网
好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库
5.3.2 搭建简单的Registry仓库
[root@docker-node1 ~]# docker load -i registry.tag.gz
ce7f800efff9: Loading layer 7.644MB/7.644MB
30609d4f10dd: Loading layer 792.6kB/792.6kB
3b6a51496c9d: Loading layer 17.55MB/17.55MB
e704e9e3e9dc: Loading layer 3.584kB/3.584kB
f019f591461d: Loading layer 2.048kB/2.048kB
Loaded image: registry:latest
[root@docker-node1 ~]# docker images
开启Registry
[root@docker-node1 ~]# docker run -d -p 5000:5000 --restart=always --name registry registry
20706cfdd2e5280950ddc58d0e7890f41f752ab484e680ca8cb8ebe7e6da565e
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
20706cfdd2e5 registry "/entrypoint.sh /etc…" 5 seconds ago Up 5 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp registry
#给要上传的经镜像打标签
#docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
[root@docker-node1 ~]# docker tag busybox:latest 172.25.254.100:5000/busybox:latest
[root@docker-node1 ~]# docker push 172.25.254.100:5000/busybox:latest
The push refers to repository [172.25.254.100:5000/busybox]
Get "https://172.25.254.100:5000/v2/": http: server gave HTTP response to HTTPS client
#配置非加密端口
[root@docker-node1 ~]# vim /etc/docker/daemon.json
{
"insecure-registries":["http://172.25.254.100:5000"]
}
[root@docker-node1 ~]# systemctl restart docker
#上传镜像
[root@docker-node1 ~]# docker push 172.25.254.100:5000/busybox:latest
The push refers to repository [172.25.254.100:5000/busybox]
d51af96cf93e: Pushed
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
#查看镜像上传
[root@docker-node1 ~]# curl 172.25.254.100:5000/v2/_catalog
{"repositories":["busybox"]}
5.3.3 为Registry提加密传输
#生成认证key和证书
[root@docker-node1 ~]# mkdir certs
[root@docker-node1 ~]# openssl req -newkey rsa:4096 \
> -nodes -sha256 -keyout certs/test.org.key \
> -addext "subjectAltName = DNS:www.test.com" \
> -x509 -days 365 -out certs/test.org.crt
#启动registry仓库
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/test.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/test.org.key registry
#为客户端建立证书
[root@docker-node1 ~]# mkdir /etc/docker/certs.d/www.test.com/ -p
[root@docker-node1 ~]# cp /root/certs/test.org.crt /etc/docker/certs.d/www.test.com/ca.crt
[root@docker-node1 ~]# systemctl restart docker
#测试
[root@docker-node1 ~]# docker tag busybox www.test.com/busybox:latest
[root@docker-node1 ~]# docker push www.test.com/busybox:latest
The push refers to repository [www.test.com/busybox]
d51af96cf93e: Pushed
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
5.3.4 为仓库建立登陆认证
#建立认证文件
[root@docker-node1 ~]# mkdir auth
[root@docker-node1 ~]# htpasswd -Bc auth/htpasswd test
New password:
Re-type new password:
Adding password for user test
#添加认证到registry容器中
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/test.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/test.org.key -v /root/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry
3b335f65a14ef5291fe56adf22fda37fd3d36fe955a73b0115f89b505dc32098
#登陆测试
[root@docker-node1 ~]# curl -k https://www.test.com/v2/_catalog -u test:redhat
{"repositories":["busybox"]}
[root@docker-node1 ~]# docker login www.test.com
Username: test
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
当仓库开启认证后必须登陆仓库才能进行镜像上传
#未登陆情况下上传镜像
[root@docker ~]# docker push www.test.com/busybox
Using default tag: latest
The push refers to repository [www.test.com/busybox]
d51af96cf93e: Preparing
no basic auth credentials
#未登陆请款下也不能下载
[root@docker-node2 ~]# docker pull www.test.com/busybox
Using default tag: latest
Error response from daemon: Head
"https://www.test.com/v2/busybox/manifests/latest": no basic auth
credentials
5.4 构建企业级私有仓库
下载软件包地址 https://github.com/goharbor/harbor/releases
Harbor 是由vmware公司开源的企业级 Docker Registry 项目。
它提供了以下主要功能和特点:
- 基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理 的灵活性。
- 镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。
- 图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。
- 审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
- 垃圾回收:可以清理不再使用的镜像,节省存储空间。
5.4.1 部署harbor
[root@docker-node1 ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker-node1 ~]# cd harbor/
[root@docker-node1 harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker-node1 harbor]# vim harbor.yml
5 hostname: www.test.com
17 certificate: /data/certs/test.org.crt
18 private_key: /data/certs/test.org.key
34 harbor_admin_password: redhat
[root@docker-node1 ~]# cp certs/test.org.crt /data/certs/test.org.crt
[root@docker-node1 ~]# cp certs/test.org.key /data/certs/test.org.key
[root@docker-node1 harbor]# ./install.sh --with-chartmuseum
#管理harbor的容器
[root@docker-node1 harbor]# docker compose stop
[root@docker-node1 harbor]# docker compose up -d
#上传镜像
[root@docker-node1 ~]# docker login www.test.com
Authenticating with existing credentials...
Stored credentials invalid or expired
Username (test): admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
[root@docker-node1 ~]# docker tag busybox:latest www.test.com/test1/busybox:latest
[root@docker-node1 ~]# docker push www.test.com/test1/busybox:latest
The push refers to repository [www.test.com/test1/busybox]
d51af96cf93e: Pushed
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
5.4.2 管理仓库
1.登陆
2.建立仓库项目
上传镜像
查看上传的镜像
六 Docker 网络
docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分
docker安装后会自动创建3种网络:bridge、host、none
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
379f9058b579 bridge bridge local
1f1aaf679312 host host local
64a9d568f680 none null local
6.1 docker原生bridge网路
docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口
[root@node1 ~]# ip link show type bridge
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:a6:ea:66:f0 brd ff:ff:ff:ff:ff:ff
- bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。
- 容器通过宿主机的NAT规则后可以访问外网
[root@docker-node1 ~]# docker run -d --name web -p 80:80 nginx
e117d06382066e2f0963bb5851f91931607ebe40b61a23fbb12abc32796c98e5
[root@docker-node1 ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ba:22:ea:b4 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27 bytes 3866 (3.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.100 netmask 255.255.255.0 broadcast 172.25.254.255
inet6 fe80::10dc:4e34:b1e0:2000 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:55:95:0d txqueuelen 1000 (Ethernet)
RX packets 2630 bytes 421690 (411.8 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2074 bytes 339687 (331.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 508 bytes 60604 (59.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 508 bytes 60604 (59.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
vethe59a8b3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::e8e7:c2ff:fe65:36b8 prefixlen 64 scopeid 0x20<link>
ether ea:e7:c2:65:36:b8 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 18 bytes 2308 (2.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
6.2 docker原生网络host
host网络模式需要在容器创建时指定 --network=host
host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少 隔离性
注意!!!!:如果公用一个网络,那么所有的网络资源都是公用的,比如启动了nginx容器那么真实主机的80端口被占 用,在启动第二个nginx容器就会失败
[root@docker-node1 ~]# docker run -it --name test --network host busybox
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:BA:22:EA:B4
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:21 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:3326 (3.2 KiB)
eth0 Link encap:Ethernet HWaddr 00:0C:29:55:95:0D
inet addr:172.25.254.100 Bcast:172.25.254.255 Mask:255.255.255.0
inet6 addr: fe80::10dc:4e34:b1e0:2000/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:825 errors:0 dropped:0 overruns:0 frame:0
TX packets:694 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:195172 (190.5 KiB) TX bytes:126886 (123.9 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:508 errors:0 dropped:0 overruns:0 frame:0
TX packets:508 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:60604 (59.1 KiB) TX bytes:60604 (59.1 KiB)
6.3 docker 原生网络none
none模式是指禁用网络功能,只有lo接口,在容器创建时使用--network=none指定
[root@docker-node1 ~]# docker run -it --name test --rm --network none busybox
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
6.4 docker的自定义网络
自定义网络模式,docker提供了三种自定义网络驱动:
bridge
overlay
macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,
overlay和macvlan是用于创建跨主机网络
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
6.4.1 自定义桥接网络
- 在建立自定以网络时,默认使用桥接模式
- 桥接默认是单调递增
- 桥接也支持自定义子网和网关
[root@docker-node1 ~]# docker network create my_net1
e911d2714ea9d07c66dfcd7d0f790bf63f66bd2e825ae0a8ee52218ce4e231ce
[root@docker-node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
5cc1606816e0 bridge bridge local
6097c99f9b54 host host local
e911d2714ea9 my_net1 bridge local
eac05d3a0460 none null local
[root@docker-node1 ~]# ifconfig
br-e911d2714ea9: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:5a:11:3d:3b txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 21 bytes 2518 (2.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ba:22:ea:b4 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27 bytes 3866 (3.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@docker-node1 ~]# docker network create my_net2 --subnet 192.168.0.0/24 --gateway 192.168.0.100
ca9e8110801bab5595930b42b3c9782cce271212ab6bf18f5659827c5e3c4cdd
[root@docker-node1 ~]# docker network inspect my_net2
[
{
"Name": "my_net2",
"Id": "ca9e8110801bab5595930b42b3c9782cce271212ab6bf18f5659827c5e3c4cdd",
"Created": "2024-08-29T11:35:19.919558195+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/24",
"Gateway": "192.168.0.100"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
6.4.2 为什么要自定义桥接
多容器之间如何互访?通过ip可以,但是有什么问题?
- docker引擎在分配ip时时根据容器启动顺序分配到,谁先启动谁用,是动态变更的
- 多容器互访用ip很显然不是很靠谱,那么多容器访问一般使用容器的名字访问更加稳定
- docker原生网络是不支持dns解析的,自定义网络中内嵌了dns
注意:不同的自定义网络是不能通讯的
[root@docker-node1 ~]# docker run -d --name web1 nginx
6c47331826ec47d8e38816381f6f9d075828ecf1232601d57c841eb500dcf8bd
[root@docker-node1 ~]# docker run -d --name web2 nginx
b8f9bf49f8208f99e16d0102a03feb85cfd9557c1e32ddb4f24b6075d8c5af2c
[root@docker-node1 ~]# docker inspect web1
[root@docker-node1 ~]# docker run -d --network my_net1 --name web nginx
06fbd8d7695bff43f5add707ef2f2c2783b43ccf5b9132ca9f512dd539365eab
[root@docker-node1 ~]# docker run -it --network my_net1 --name test busybox
/ # ping web
PING web (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.298 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.100 ms
6.4.3 如何让不同的自定义网络互通?
[root@docker-node1 ~]# docker run -d --name web1 --network my_net1 nginx
[root@docker-node1 ~]# docker network connect my_net1 test
[root@docker-node1 ~]# docker run -it --name test --network my_net2 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:00:01
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:13 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1630 (1.5 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:00:01
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:18 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2388 (2.3 KiB) TX bytes:0 (0.0 B)
eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:04
inet addr:172.18.0.4 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:516 (516.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.203 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.259 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.098 ms
6.4.4 joined容器网络
Joined容器一种较为特别的网络模式,•在容器创建时使用--network=container:vm1指定。(vm1指定 的是运行的容器名)
处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
[root@docker-node1 ~]# docker run -it --rm --network container:web1 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:03
inet addr:172.18.0.3 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:21 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2450 (2.3 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
[root@docker-node1 ~]# docker run -it --rm --network container:web1 centos:7
[root@36d58d4314d3 /]# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
6.4.5 joined网络示例演示
利用容器部署phpmyadmin管理mysql
注意!!!!:开启的phpmyadmin容器中是没有数据库的,这里填写的localhost:3306是因为mysql容器和phpmyadmin容器公用一个网络站
[root@docker-node1 ~]# docker load -i mysql-5.7.tar.gz
[root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz
[root@docker-node1 ~]# docker run -d --name mysqladmin --network my_net1 \
> -e PMA_ARBITRARY=1 \
> -p 80:80 phpmyadmin:latest
523f241bbbbbe6186b0fd89c974096927aa87f938e389969dd79dfc2988aadb0
[root@docker-node1 ~]# docker run -d --name mysql \
> -e MYSQL_ROOT_PASSWORD='redhat' \
> --network container:mysqladmin \
> mysql:5.7
98c4710f682b012a721402c308505c3b1b566184424af9872c4f483ac01e1164
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
98c4710f682b mysql:5.7 "docker-entrypoint.s…" About a minute ago Up About a minute mysql
523f241bbbbb phpmyadmin:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp mysqladmin
f37bbc10b61a busybox "sh" 53 minutes ago Up 53 minutes sweet_mcnulty
[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# mysql -uroot -predhat