Docker简单使用教程

作者 qin lang

部分资料借鉴 cloudman

What - 什么是容器?

容器是一种轻量级、可移植、自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行。开发人员在自己笔记本上创建并测试好的容器,无需任何修改就能够在生产系统的虚拟机、物理服务器或公有云主机上运行。

容器与虚拟机
谈到容器,就不得不将它与虚拟机进行对比,因为两者都是为应用提供封装和隔离。

容器由两部分组成:
1 应用程序本身
2 依赖:比如应用程序需要的库或其他软件

容器在 Host 操作系统的用户空间中运行,与操作系统的其他进程隔离。这一点显著区别于的虚拟机。

传统的虚拟化技术,比如 VMWare, KVM, Xen,目标是创建完整的虚拟机。为了运行应用,除了部署应用本身及其依赖(通常几十 MB),还得安装整个操作系统(几十 GB)。

Why - 为什么需要容器?

为什么需要容器?容器到底解决的是什么问题?
简要的答案是:容器使软件具备了超强的可移植能力。

容器解决的问题

我们来看看今天的软件开发面临着怎样的挑战?

如今的系统在架构上较十年前已经变得非常复杂了。以前几乎所有的应用都采用三层架构(Presentation/Application/Data),系统部署到有限的几台物理服务器上(Web Server/Application Server/Database Server)。

而今天,开发人员通常使用多种服务(比如 MQ,Cache,DB)构建和组装应用,而且应用很可能会部署到不同的环境,比如虚拟服务器,私有云和公有云。

一方面应用包含多种服务,这些服务有自己所依赖的库和软件包;另一方面存在多种部署环境,服务在运行时可能需要动态迁移到不同的环境中。这就产生了一个问题:

如何让每种服务能够在所有的部署环境中顺利运行?

于是我们得到了下面这个矩阵:

各种服务和环境通过排列组合产生了一个大矩阵。开发人员在编写代码时需要考虑不同的运行环境,运维人员则需要为不同的服务和平台配置环境。对他们双方来说,这都是一项困难而艰巨的任务。

如何解决这个问题呢?

聪明的技术人员从传统的运输行业找到了答案。

几十年前,运输业面临着类似的问题。

每一次运输,货主与承运方都会担心因货物类型的不同而导致损失,比如几个铁桶错误地压在了一堆香蕉上。另一方面,运输过程中需要使用不同的交通工具也让整个过程痛苦不堪:货物先装上车运到码头,卸货,然后装上船,到岸后又卸下船,再装上火车,到达目的地,最后卸货。一半以上的时间花费在装、卸货上,而且搬上搬下还容易损坏货物。

这同样也是一个 NxM 的矩阵。

幸运的是,集装箱的发明解决这个难题。

任何货物,无论钢琴还是保时捷,都被放到各自的集装箱中。集装箱在整个运输过程中都是密封的,只有到达最终目的地才被打开。标准集装箱可以被高效地装卸、重叠和长途运输。现代化的起重机可以自动在卡车、轮船和火车之间移动集装箱。集装箱被誉为运输业与世界贸易最重要的发明。

Docker 将集装箱思想运用到软件打包上,为代码提供了一个基于容器的标准化运输系统。Docker 可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上。

其实,“集装箱” 和 “容器” 对应的英文单词都是 “Container”。
“容器” 是国内约定俗成的叫法,可能是因为容器比集装箱更抽象,更适合软件领域的原故吧。

我个人认为:在老外的思维中,“Container” 只用到了集装箱这一个意思,Docker 的 Logo 不就是一堆集装箱吗?

Docker 的特性
我们可以看看集装箱思想是如何与 Docker 各种特性相对应的。

Docker 的核心组件包括:

Docker 客户端 - Client
Docker 服务器 - Docker daemon
Docker 镜像 - Image
Registry
Docker 容器 - Container

Docker 服务器

Docker daemon 是服务器组件,以 Linux 后台服务的方式运行。

Docker daemon 运行在 Docker host 上,负责创建、运行、监控容器,构建、存储镜像。

默认配置下,Docker daemon 只能响应来自本地 Host 的客户端请求。如果要允许远程客户端请求,需要在配置文件中打开 TCP 监听,步骤如下:

编辑配置文件 /etc/systemd/system/multi-user.target.wants/docker.service,在环境变量 ExecStart 后面添加 -H tcp://0.0.0.0,允许来自任意 IP 的客户端连接。
如果使用的是其他操作系统,配置文件的位置可能会不一样。

重启 Docker daemon。

服务器 IP 为 192.168.56.102,客户端在命令行里加上 -H 参数,即可与远程服务器通信。
info 子命令用于查看 Docker 服务器的信息。

Docker 镜像

可将 Docker 镜像看着只读模板,通过它可以创建 Docker 容器。

例如某个镜像可能包含一个 Ubuntu 操作系统、一个 Apache HTTP Server 以及用户开发的 Web 应用。

镜像有多种生成方法:

可以从无到有开始创建镜像

也可以下载并使用别人创建好的现成的镜像

还可以在现有镜像上创建新的镜像

Docker 容器

Docker 容器就是 Docker 镜像的运行实例。

用户可以通过 CLI(docker)或是 API 启动、停止、移动或删除容器。可以这么认为,对于应用软件,镜像是软件生命周期的构建和打包阶段,而容器则是启动和运行阶段。

Registry

Registry 是存放 Docker 镜像的仓库,Registry 分私有和公有两种。

Docker Hub(https://hub.docker.com/) 是默认的 Registry,由 Docker 公司维护,上面有数以万计的镜像,用户可以自由下载和使用。
ECR AWS 公司容器存放位置

docker pull 命令可以从 Registry 下载镜像。
docker run 命令则是先下载镜像(如果本地没有),然后再启动容器。

安装 Docker

yum -y install docker

运行第一个容器

环境就绪,马上运行第一个容器,执行命令:

docker run -d -p 80:80 httpd

其过程可以简单的描述为:

  • 从 Docker Hub 下载 httpd 镜像。镜像中已经安装好了 Apache HTTP Server。
  • 启动 httpd 容器,并将容器的 80 端口映射到 host 的 80 端口。第一个80是主机端口 第二个80是容器端口

容器启动过程如下:

Docker 客户端执行 docker run 命令。

Docker daemon 发现本地没有 httpd 镜像。

daemon 从 Docker Hub 下载镜像。

下载完成,镜像 httpd 被保存到本地。

Docker daemon 启动容器。

hello-world - 最小的镜像

hello-world 是 Docker 官方提供的一个镜像,通常用来验证 Docker 是否安装成功。

docker pull hello-world

[root@ip-172-29-140-52 ~]# docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:49a1c8800c94df04e9658809b006fd8a686cab8028d33cfba2cc049724254202
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest

Docker 常用命令

# 容器信息获取命令
docker ps               #列出当前运行中的容器
docker ps -a            #列出该机器上所有的容器,包括启动和未启动的
docker images           #列出该机器上所有的镜像
docker top 容器id         #获取容器的top信息
docker stats 容器id       #获取容器容器信息
docker logs 容器id        #获取容器的输出日志
docker logs -f 容器id     #实时获取容器的日志
docker inspect 容器ID     #查看容器信息
docker history 镜像ID     #查看容器的历史构建记录# 容器操作命令
docker tag 镜像   新的名字    例如  docker tag nginx:latest wuerp-nginx:latest #新打出来的包会单独的存在
docker run #启动容器-i  以交互模式运行容器,通常与 -t 同时使用;-t  为容器重新分配一个伪输入终端,通常与 -i 同时使用;-d 后台运行容器,并返回容器ID;
docker cp 文件 容器id:/root #把文件cp到容器的root目录下
docker cp 容器id:/root/wuerp.conf . #把容器/root/wuerp.conf的文件拷贝到本地
docker start 容器id       #启动容器,在容器停止的时候使用
docker stop 容器id        #停止容器,在容器启动的时候使用
docker restart 容器id     #重启容器
docker pause 容器id       #暂停容器
docker unpause 容器id     #取暂停容器
docker rm 容器id          #删除容器
docker rmi 镜像id         #删除镜像ID
小技巧 删除所有容器 docker ps $(docker ps -a -q)删除容器镜像 docker rmi $(docker images)
docker rename 容器名字  新的容器名字  #给容器--name 属性的值改名
docker exec -it 容器id /bin/bash  #进入容器使用/bin/bash解释器
docker container update --restart=always 容器ID      #更新容器的一些属性 例如这更新容器的启动属性 always docker启动的时候会自动启动容器#容器获取上传命令
docker login            #登录镜像仓库 默认情况是登录dockerhub的,可以自己去注册一个
#登录公司的ECR仓库方法   aws ecr get-login-password --region cn-northwest-1 | docker login --username AWS --password-stdin
097364988641.dkr.ecr.cn-northwest-1.amazonaws.com.cn
docker logout           #退出镜像仓库
docker search 镜像       # 在dockerhub搜索容器镜像
docker pull             #镜像仓库/镜像:标签  #拉取镜像到本地
docker push             #推送镜像到仓库    docker push 097364988641.dkr.ecr.cn-northwest-1.amazonaws.com.cn/local_dotnet_core:latest   #注意,镜像是什么名字,推送到的镜像仓库就是什么名字

创建一个复杂一点的docker容器

docker run -it -p 8080:80 -v /root/2020-07-29:/root/log --name nginx --restart=always nginx

-p 8080:80 将本机的8080端口映射到容器的80上

-v /root/2020-07-29:/root/log 把本机的/root/2020-07-29文件夹挂载到容器的/root/log下

–name nginx 给容器启一个名字

–restart=always 容器启动策略,会自动重启容器

最后的nginx是Images的名称,如果没有就从dockerhub上默认拉取

docker 镜像加速

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

docker镜像分层

基础镜像

Linux 操作系统由内核空间和用户空间组成。如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TnPAL5M2-1623205435987)(1E33BB6B44954BA992EE1172FF4F9F0C)]

rootfs

内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。

用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。

对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。

而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到 10MB。

我们平时安装的 CentOS 除了 rootfs 还会选装很多软件、服务、图形桌面等,需要好几个 GB 就不足为奇了。

base 镜像提供的是最小安装的 Linux 发行版

下面是 CentOS 镜像的 Dockerfile 的内容:

FROM scratch
ADD centos-7-docker.tar.xz
CMD ["/bin/bash"]

第二行 ADD 指令添加到镜像的 tar 包就是 CentOS 7 的 rootfs。在制作镜像时,这个 tar 包会自动解压到 / 目录下,生成 /dev, /porc, /bin 等目录。

注:可在 Docker Hub 的镜像描述页面中查看 Dockerfile 。

https://hub.docker.com/

不同 Linux 发行版的区别主要就是 rootfs。

比如 Ubuntu 14.04 使用 upstart 管理服务,apt 管理软件包;而 CentOS 7 使用 systemd 和 yum。这些都是用户空间上的区别,Linux kernel 差别不大。

所以 Docker 可以同时支持多种 Linux 镜像,模拟出多种操作系统环境。

镜像分层

Docker 支持通过扩展现有镜像,创建新的镜像。

实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。比如我们现在构建一个新的镜像,Dockerfile 如下:

FROM centos
RUN yum -y install wget
RUN yum -y install zip
CMD ["/bin/bash"]

① 新镜像不再是从 scratch 开始,而是直接在 centos 镜像上构建。
② 安装 wget。
③ 安装 zip。
④ 容器启动时运行 bash。

[root@ip-172-29-140-52 ~]# docker build -t wuerp-test .
Sending build context to Docker daemon  465.7MB
Step 1/4 : FROM centos
latest: Pulling from library/centos
6910e5a164f7: Pull complete
Digest: sha256:4062bbdd1bb0801b0aa38e0f83dece70fb7a5e9bce223423a68de2d8b784b43b
Status: Downloaded newer image for centos:latest---> 831691599b88
Step 2/4 : RUN yum -y install wget---> Running in b6e2f927de4d
CentOS-8 - AppStream                            1.7 MB/s | 5.8 MB     00:03
CentOS-8 - Base                                 736 kB/s | 2.2 MB     00:03
CentOS-8 - Extras                               7.4 kB/s | 7.0 kB     00:00
Last metadata expiration check: 0:00:01 ago on Fri Jul 31 14:00:18 2020.
Dependencies resolved.
================================================================================Package                    Arch      Version                Repository    Size
================================================================================
Installing:wget                       x86_64    1.19.5-8.el8_1.1       AppStream    735 k
Installing dependencies:libpsl                     x86_64    0.20.2-5.el8           BaseOS        61 kpublicsuffix-list-dafsa    noarch    20180723-1.el8         BaseOS        56 kTransaction Summary
================================================================================
Install  3 PackagesTotal download size: 852 k
Installed size: 3.0 M
Downloading Packages:
(1/3): publicsuffix-list-dafsa-20180723-1.el8.n 200 kB/s |  56 kB     00:00
(2/3): libpsl-0.20.2-5.el8.x86_64.rpm            96 kB/s |  61 kB     00:00
(3/3): wget-1.19.5-8.el8_1.1.x86_64.rpm         666 kB/s | 735 kB     00:01
--------------------------------------------------------------------------------
Total                                           343 kB/s | 852 kB     00:02
warning: /var/cache/dnf/AppStream-02e86d1c976ab532/packages/wget-1.19.5-8.el8_1.1.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
CentOS-8 - AppStream                            1.6 MB/s | 1.6 kB     00:00
Importing GPG key 0x8483C65D:Userid     : "CentOS (CentOS Official Signing Key) <security@centos.org>"Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65DFrom       : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transactionPreparing        :                                                        1/1 Installing       : publicsuffix-list-dafsa-20180723-1.el8.noarch          1/3 Installing       : libpsl-0.20.2-5.el8.x86_64                             2/3 Installing       : wget-1.19.5-8.el8_1.1.x86_64                           3/3 Running scriptlet: wget-1.19.5-8.el8_1.1.x86_64                           3/3 Verifying        : wget-1.19.5-8.el8_1.1.x86_64                           1/3 Verifying        : libpsl-0.20.2-5.el8.x86_64                             2/3 Verifying        : publicsuffix-list-dafsa-20180723-1.el8.noarch          3/3 Installed:libpsl-0.20.2-5.el8.x86_64     publicsuffix-list-dafsa-20180723-1.el8.noarch  wget-1.19.5-8.el8_1.1.x86_64  Complete!
Removing intermediate container b6e2f927de4d---> 15030461b7ce
Step 3/4 : RUN yum -y install zip---> Running in 2739aa93af31
Last metadata expiration check: 0:00:06 ago on Fri Jul 31 14:00:18 2020.
Dependencies resolved.
================================================================================Package         Architecture     Version                Repository        Size
================================================================================
Installing:zip             x86_64           3.0-23.el8             BaseOS           270 k
Installing dependencies:unzip           x86_64           6.0-43.el8             BaseOS           195 kTransaction Summary
================================================================================
Install  2 PackagesTotal download size: 465 k
Installed size: 1.2 M
Downloading Packages:
(1/2): zip-3.0-23.el8.x86_64.rpm                289 kB/s | 270 kB     00:00
(2/2): unzip-6.0-43.el8.x86_64.rpm              170 kB/s | 195 kB     00:01
--------------------------------------------------------------------------------
Total                                           260 kB/s | 465 kB     00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transactionPreparing        :                                                        1/1 Installing       : unzip-6.0-43.el8.x86_64                                1/2 Installing       : zip-3.0-23.el8.x86_64                                  2/2 Running scriptlet: zip-3.0-23.el8.x86_64                                  2/2 Verifying        : unzip-6.0-43.el8.x86_64                                1/2 Verifying        : zip-3.0-23.el8.x86_64                                  2/2 Installed:unzip-6.0-43.el8.x86_64                 zip-3.0-23.el8.x86_64                Complete!
Removing intermediate container 2739aa93af31---> e6882e168358
Step 4/4 : CMD ["/bin/bash"]---> Running in f62d45699df5
Removing intermediate container f62d45699df5---> bb1e77a27181
Successfully built bb1e77a27181
Successfully tagged wuerp-test:latest

可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

问什么 Docker 镜像要采用这种分层结构呢?

最大的一个好处就是 - 共享资源

比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享,我们将在后面更深入地讨论这个特性。

这时可能就有人会问了:如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是否也会被修改?

答案是不会!
修改会被限制在单个容器内。
这就是我们接下来要学习的容器 Copy-on-Write 特性。

可写的容器层

当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。

只有容器层是可写的,容器层下面的所有镜像层都是只读的

下面我们深入讨论容器层的细节。

镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。

  1. 添加文件
    在容器中创建文件时,新文件被添加到容器层中。
  2. 读取文件
    在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
  3. 修改文件
    在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
  4. 删除文件
    在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。

只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。

这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享

*小技巧 在上面的镜像层构建较大不常常改动的内容,例如上面安装许多软件,在下面放置配置文件,但是配置文件可能会经常改动,如果配置文件在安装包上面的话,每次构建的时候检测到每一层的md5值变化,就会从产生变化的镜像层开始重新构建

实战docker使用小案例

以目前准备使用的keycloak和Mysql举例

Docker安装MySQL

创建mysql配置文件

mkdir -p {conf,data,logs,backup}

vim $PWD/conf/my.cnf

[client]
default-character-set = utf8[mysql]
default-character-set = utf8[mysqld]
character_set_server = utf8
collation-server = utf8_bin
transaction_isolation = READ-COMMITTED

启动mysql镜像

docker run --name mysql --restart always  -p 3306:3306   -e MYSQL_ROOT_PASSWORD=wuerp -v $PWD/data:/var/lib/mysql  -v $PWD/logs:/logs   -v $PWD/conf:/etc/mysql/conf.d  -v $PWD/backup:/backup -itd  mysql:5.7
  • 启动一个名字叫做mysql 启动策略总是启动的容器
  • -p 映射的端口把本地3306 映射到容器的3306
  • -e 传递环境变量到容器内 这里传入一个password
  • -v 把$pwd/data 映射到/var/lib/mysql这个位置 把当前目录下的pwd
  • -v 把$pwd/logs映射到/logs
  • -v 把$pwd/backup 映射到/backup
  • -itd 把容器放在后台运行返回容器id
  • mysql:5.7 使用的镜像版本
[root@ip-172-29-140-52 test]# docker run --name mysql --restart always  -p 3306:3306  -e MYSQL_ROOT_PASSWORD=wuerp -v $PWD/data:/var/lib/mysql  -v $PWD/logs:/logs -v $PWD/conf:/etc/mysql/conf.d  -v $PWD/backup:/backup -itd  mysql:5.7
Unable to find image 'mysql:5.7' locally
5.7: Pulling from library/mysql
6ec8c9369e08: Already exists
177e5de89054: Pull complete
ab6ccb86eb40: Pull complete
e1ee78841235: Pull complete
09cd86ccee56: Pull complete
78bea0594a44: Pull complete
caf5f529ae89: Pull complete
4e54a8bcf566: Pull complete
50c21ba6527b: Pull complete
68e74bb27b39: Pull complete
5f13eadfe747: Pull complete
Digest: sha256:97869b42772dac5b767f4e4692434fbd5e6b86bcb8695d4feafb52b59fe9ae24
Status: Downloaded newer image for mysql:5.7
ceb20e33681d239e0e9cde25d9a4eeb713354895f70c8447d2b423ced86b6203
[root@ip-172-29-140-52 test]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
ceb20e33681d        mysql:5.7           "docker-entrypoint.s…"   3 seconds ago       Up 2 seconds        0.0.0.0:3306->3306/tcp, 33060/tcp   mysql
a4ce76b48985        nginx               "/docker-entrypoint.…"   6 minutes ago       Up 6 minutes        80/tcp                              funny_lederberg
[root@ip-172-29-140-52 test]# docker exec -it mysql /bin/bash
root@ceb20e33681d:/# ls
backup  bin  boot  dev  docker-entrypoint-initdb.d  entrypoint.sh  etc  home  lib  lib64  logs  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@ceb20e33681d:/# mysql -uroot -pwuerp
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.31 MySQL Community Server (GPL)Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)mysql> 

成功访问,mysql安装成功

Docker安装keycloak

# KEYCLOAK_USER 用户名
# KEYCLOAK_PASSWORD 密码
# DB_ADDR 数据库地址
# DB_PORT数据库端口
# DB_DATABASE 数据库名称
# DB_USER 数据库用户
# DB_PASSWORD 数据库密码docker run \-d \--name keycloak \-p 8080:8080 \-p 8443:8443 \-e KEYCLOAK_USER=admin \-e KEYCLOAK_PASSWORD=123456 \-e DB_ADDR=127.0.0.1 \-e DB_PORT=3306 \-e DB_DATABASE=keycloak \-e DB_USER=root \-e DB_PASSWORD=wuerp \jboss/keycloak:latest

访问https的keycloak

访问该机器 https://localhost:8443


docker简单使用教程相关推荐

  1. Docker最全教程——从理论到实战(六)

    Docker最全教程--从理论到实战(六) 原文:Docker最全教程--从理论到实战(六) 托管到腾讯云容器服务 托管到腾讯云容器服务,我们的公众号"magiccodes"已经发 ...

  2. Docker最全教程——从理论到实战(一)

    Docker最全教程--从理论到实战(一) 目录 前言 随着生产力的发展尤其是弹性架构的广泛应用(比如微服务),许多一流开发者都将应用托管到了应用容器上,比如Google.微软.亚马逊.腾讯.阿里.京 ...

  3. Docker最全教程——Redis容器化以及排行榜实战(十三)

    Docker最全教程--Redis容器化以及排行榜实战(十三) 原文:Docker最全教程--Redis容器化以及排行榜实战(十三) 前言 容器教程的路还很长,笔者尽量根据实践来不断地完善.由于在编写 ...

  4. Docker最全教程——从理论到实战(七)

    Docker最全教程--从理论到实战(七) 原文:Docker最全教程--从理论到实战(七) 在本系列教程中,笔者希望将必要的知识点围绕理论.流程(工作流程).方法.实践来进行讲解,而不是单纯的为讲解 ...

  5. Docker最全教程之使用.NET Core推送钉钉消息(二十)

    前言 上一篇我们通过实战分享了使用Go推送钉钉消息,由于技痒,笔者现在也编写了一个.NET Core的Demo,作为简单的对照和说明. 最后,由于精力有限,笔者希望有兴趣的朋友可以分享下使用CoreR ...

  6. Docker最全教程之使用TeamCity来完成内部CI、CD流程(十七)

    本篇教程主要讲解基于容器服务搭建TeamCity服务,并且完成内部项目的CI流程配置.教程中也分享了一个简单的CI.CD流程,仅作探讨.不过由于篇幅有限,完整的DevOps,我们后续独立探讨. 为了降 ...

  7. Docker最全教程之树莓派和Docker(十六)

    前言 树莓派(Raspberry Pi)是一台卡片电脑(只有信用卡大小),我们可以使用树莓派做很多事情,比如智能家居的中控.航空器.BT下载器.挖矿机.智能机器人.小型服务器(花生壳+网站)等等. 目 ...

  8. Docker最全教程之使用Tencent Hub来完成CI(十)

    本周更新两篇,保证不太监! 在本系列教程中,笔者希望将必要的知识点围绕理论.流程(工作流程).方法.实践来进行讲解,而不是单纯的为讲解知识点而进行讲解.也就是说,笔者希望能够让大家将理论.知识.思想和 ...

  9. Docker最全教程——从理论到实战(九)

    在本系列教程中,笔者希望将必要的知识点围绕理论.流程(工作流程).方法.实践来进行讲解,而不是单纯的为讲解知识点而进行讲解.也就是说,笔者希望能够让大家将理论.知识.思想和指导应用到工作的实际场景和实 ...

最新文章

  1. AlphaGo制胜绝招:蒙特卡洛树搜索入门指南
  2. python一个月能学成嘛-Python 从入门到精通:一个月就够了!
  3. 出现“adb不是内部或外部命令,也不是可运行的程序或批量文件。”
  4. 《Linux高性能服务器编程》学习笔记
  5. 蒙娜丽莎,品牌创新的探索者
  6. centos 升级php5.5_CentOS 5.x 系统yum 升级php到5.2.x的方法(测试可用)
  7. 项目总结一:情感分类项目(emojify)
  8. /etc/udev/rules.d/10-usbstorage.rules
  9. 数据库中常见mdf 、ndf 、ldf 、文件
  10. regsvr32注册Dll文件时出现0x80004005问题的解决方案
  11. html水印生成pdf,如何在jsPDF中添加PDF生成水印?
  12. 云中漫步-我这一辈子
  13. Windows10彻底关闭休眠功能
  14. abp The value could not be converted to a GUID:
  15. 操作系统学习笔记(二十二)~虚拟存储技术+请求分页+页面置换
  16. 带有Arduino的WS2812B可寻址RGB LED灯条指南
  17. 插件化框架集成-360插件框架DroidPlug
  18. 团队对员工工作积极性的影响
  19. IDEA 出现 Exception in thread main java.lang.OutOfMemoryError: Java heap space 解决方式
  20. 【mysql innodb索引结构B+树】

热门文章

  1. Java程序的运行机制
  2. mysql-8.0.32-winx64 下载
  3. 2017-08-03 面试记录(铃声多多)
  4. 群消息,究竟存1份还是多份?
  5. exe 网页套壳_Nativefier——可以把网页打包成exe的工具
  6. 五个维度让你更加了解闲鱼无货源玩法
  7. Ubuntu笔记本电脑打不开蓝牙的解决办法
  8. Linux实战教学笔记06:Linux系统基础优化
  9. iOS - 用Hopper反编译 Nike+ 二进制文件
  10. 报错Error querying database. Cause:java.lang.NullPointException