mac系统通过dockerfile运行centos8-ssh

20241127072831

背景

上一节,我们通过使用docker 命令以及进入容器内安装命令等,安装和运行了centos8和ssh。你会发现,我们的任何操作和修改都需要进入容器内部。

这时候,dockerfiled就派上用场了。我们只需要创建一个dockerfile文件,任何改动和更新只需要编辑dockerfile即可。

如果你是docker初学者,强烈建议先去阅读和操作前一篇mac系统docker运行centos8-ssh。然后再回来阅读和操作本篇,就会清晰的知道 看到 dockerfile的优点和益处。对dockerfile的作用有更深入和更清晰的理解。

系统

MacOS Monterey 12.7.1 芯片:intel

为了完整的展示从0到1的整个过程,会一步一步的把遇到的问题真实的体现出来。如果想直接去看完整dockerfile,去附录即可。

20241127073307

制作dockerfile

创建和编辑dockerfile

  • $ cd /Users/{user}/test-docker/test-docker-file
  • touch Dockerfile
  • chmod +x Dockerfile

编辑内容,添加以下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## test
## 默认是centos:latest

FROM centos

LABEL org.opencontainers.image.authors="xxx@gmail.com"

RUN yum update -y \
&& yum install -y openssh-server \
&& echo 'root:yourpassword' |chpasswd \

EXPOSE 22

CMD ["/usr/sbin/sshd","-D"]

如果对dockerfile指令不熟悉,可以参见dockerfile指令详解

脚本很简单,引用centos latest,使用yum安装ssh,给容器root用户设置密码,暴露22端口,定义容器启动时第一个执行的程序(命令)。

dockerfile制作完了,然后就是构建这个脚本了。

构建

我们给新镜像定义name:test-ssh-from-docker-file

  • $ docker build -t test-ssh-from-docker-file .

执行后发现报错了,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[+] Building 4.8s (5/5) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 454B
=> [internal] load metadata for docker.io/library/centos:latest
=> [internal] load .dockerignore
=> => transferring context: 2B
=> CACHED [1/2] FROM docker.io/library/centos:latest
=> ERROR [2/2] RUN yum update && yum install -y openssh-server && mkdir /var/run/sshd && echo 'root:root123' |chpasswd
------
> [2/2] RUN yum update && yum install -y openssh-server && mkdir /var/run/sshd && echo 'root:root123' |chpasswd:
4.706 CentOS Linux 8 - AppStream 0.0 B/s | 0 B
4.706 Errors during downloading metadata for repository 'appstream':
4.706 - Status code: 502 for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container (IP: 18.225.36.18)
4.714 Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: Status code: 502 for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container (IP: 18.225.36.18)
------
Dockerfile:11
--------------------
10 |
## refer to http://www.dockerinfo.net/%e6%a1%88%e4%be%8b-%e5%9c%a8docker%e4%b8%ad%e8%bf%90%e8%a1%8cssh%e8%bf%9b%e7%a8%8b%e6%9c%8d%e5%8a%a1
11 | >>> RUN yum update \
## refer to http://www.dockerinfo.net/%e6%a1%88%e4%be%8b-%e5%9c%a8docker%e4%b8%ad%e8%bf%90%e8%a1%8cssh%e8%bf%9b%e7%a8%8b%e6%9c%8d%e5%8a%a1
12 | >>> && yum install -y openssh-server \
## refer to http://www.dockerinfo.net/%e6%a1%88%e4%be%8b-%e5%9c%a8docker%e4%b8%ad%e8%bf%90%e8%a1%8cssh%e8%bf%9b%e7%a8%8b%e6%9c%8d%e5%8a%a1
13 | >>> && mkdir /var/run/sshd \

截屏2024-11-25-2

原因:大概意思是mirrorlist不提供维护了,需要将mirrorlist改为baseurl;同时需要将baseurl的地址mirror.centos.org 改为 vault.centos.org

所以,解决方案(参考:mirrorlist-centos-org-no-longer-resolve)时脚本中添加如下命令用以更新地址。

1
2
3
sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/CentOS-*.repo \
&& sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/CentOS-*.repo \
&& sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/CentOS-*.repo \

再次构建 docker build -t test-ssh-from-docker-file .

构建没有报错。

20241127073333

docker容器运行镜像

这时,我们可以启动这个镜像了

  • $ docker run -d –privileged -p 5007:22 –name test-ssh-from-docker-file-container test-ssh-from-docker-file

查看实例

  • docker container ls -a

发现容器状态是Exited,正常是Running。

看来是构建成功了,但是容器内执行指令时有错误。这时,就需要看看容器的日志了。

查看docker容器日志

查看docker容器日志有两种方式。一种是进入容器中(docker exec)(问题:但如果容器没有启动,无法进入)。一种是通过docker logs

  • $ docker logs test-ssh-from-docker-file-container

运行这个命令,就可以看到这个容器的日志

1
2
3
4
Unable to load host key: /etc/ssh/ssh_host_rsa_key
Unable to load host key: /etc/ssh/ssh_host_ecdsa_key
Unable to load host key: /etc/ssh/ssh_host_ed25519_key
sshd: no hostkeys available -- exiting.

错误的原因是没有生成对应的ssh key。解决方案(参考:ssh-could-not-load-host-key)是dockerfile中增加如下

1
/usr/bin/ssh-keygen -A

我们再次构建 docker build -t test-ssh-from-docker-file .。但之前已经生成对应的镜像了(虽然它没运行起来)。需要使用 docker rm container test-ssh-from-docker-file-container 删除镜像实例,docker image rm test-ssh-from-docker-file 删除镜像。

再次构建,没有报错信息;再次运行镜像,查看 docker logs,没有错误日志。执行 docker container ls 发现 test-ssh-from-docker-file-container 的状态是Running了。

截屏2024-11-26-1

此时,容器是创建和运行成功了。

我们就可以进入容器内部了。

进入容器内部

  • $ docker exec -it test-ssh-from-docker-file-container bash

执行命令后就进入centos8容器内了。这时,可以执行命令,如查看容器的进程 ps -ef

20241127073440

客户端通过ssh连接容器

我们新打开一个终端窗口,可以通过 docker port 查看容器内部端口对外暴露端口
docker port test-ssh-from-docker-file-container 22

然后执行ssh命令

  • $ ssh root@localhost -p 5007
1
2
3
4
5
The authenticity of host '[localhost]:5007 ([::1]:5007)' can't be established.
ED25520 key fingerprint is SHA256:jwnqbOUiW1gMJYQv52eabc.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:5007' (ED25520) to the list of known hosts.

可以看到,连接成功了。

如果想停止容器实例,可以执行 docker stop test-ssh-from-docker-file-container

此时,我们已经通过Dockerfile制作了 test-ssh-from-docker-file 镜像和成功运行了镜像实例 test-ssh-from-docker-file-container
我们只需要将这个做好的镜像push到docker hub即可。

推送镜像到docker hub

  • $ docker push test-ssh-from-docker-file

报错了,提示没有权限

1
2
3
4
The push refers to repository [docker.io/library/test-ssh-from-docker-file]
f6e6bced2702: Preparing
74ddd0ec08fa: Preparing
denied: requested access to the resource is denied

  • $ docker image ls
    查看镜像
    1
    2
    REPOSITORY                        TAG        IMAGE ID       CREATED          SIZE
    test-ssh-from-docker-file v1 b3fd18bb5d2d 24 minutes ago 302MB

解决方案:我们重新tag下,将镜像加上你的docker hub的用户名。如yourUserName=test123

  • $ docker tag test-ssh-from-docker-file test123/test-ssh-from-docker-file

再次push到docker hub

  • $ docker push test123/test-ssh-from-docker-file
    1
    2
    3
    4
    The push refers to repository [docker.io/{yourUserName}/test-ssh-from-docker-file]
    f6e6bced2702: Pushed
    74ddd0ec08fa: Pushed
    v1: digest: sha256:123ed4e883cecef8180433b3a21d11b1e383d9da68bac01694b1c84575e3e72b size: 333

成功了。

我们通过docker desktop也可以看到hub上的镜像,如图

截屏2024-11-17-9

20241127073502

附录

docker run 参数说明

说明

1
2
3
4
5
6
- $ docker run -d --privileged -p 5007:22 --name test-ssh-from-docker-file-container test-ssh-from-docker-file

-d:后台运行
-p:指定外部端口映射容器内部的端口
-P:随机一个外部端口映射容器内部的端口,优先使用dockerfile中EXPOSE指定的
--privileged:特权模式,相当于管理员权限

参考
Could not retrieve mirrorlist的解决方法

完整的dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
## test
## 默认是centos:latest

FROM centos

LABEL org.opencontainers.image.authors="xxx@gmail.com"

RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/CentOS-*.repo \
&& sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/CentOS-*.repo \
&& sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/CentOS-*.repo \
&& yum update -y \
&& yum install -y openssh-server \
&& echo 'root:yourpassword' |chpasswd \
&& /usr/bin/ssh-keygen -A

EXPOSE 22

CMD ["/usr/sbin/sshd","-D"]

dockerfile制作与运行docker镜像-模版

  1. 制作dockerfile
    创建和编辑dockerfile

    1
    2
    3
    4
    5
    $ cd /Users/yourDir
    $ touch Dockerfile
    $ chmod +x Dockerfile

    Dockerfile 添加 docker 命令
  2. 构建docker镜像

1
$ docker build -t yourImageName .
  1. 运行这个镜像
1
$ docker run -d –privileged -p yourOutPort:yourInPort –name yourContainerName yourImageName