自学 docker,自己写的 Dockerfile 语法编译通过不了,有哪些错误,请前辈指正 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
slove
V2EX    Docker

自学 docker,自己写的 Dockerfile 语法编译通过不了,有哪些错误,请前辈指正

  •  
  •   slove 2022-12-06 14:01:54 +08:00 via iPhone 3538 次点击
    这是一个创建于 1041 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #基于 ubuntu 最新版镜像
    FROM ubuntu:latest
    #更新安装包列表
    RUN apt update
    #安装 apache2
    RUN apt install apache2
    #安装 mysql-server
    RUN apt install mysql-server
    #启动 mysql
    RUN service mysql start
    #登陆 mysql
    RUN mysql
    #修改 root 密码
    RUN alter user “root”@“localhost” identified with mysql_native_password by “12345”;
    #root 密码生效
    RUN flush privileges ;
    #新建数据库
    RUN create database wordoress ;
    #新建用户
    RUN create user “solve”@“localhost” identufied by “888888”;
    #配置数据库用户
    RUN grant all on wordpress.* to “slove”@“localhost” with grant option ;
    #配置生效
    RUN flush privileges ;
    #退出数据库
    RUN exit
    #下载 wordpress 最新版到指定 /var/www/html/
    ADD https://cn.wordpress.org/latest-zh_CN.tar.gz /var/www/html
    #开放端口号
    EXPOSE 80
    CMD
    38 条回复    2023-03-02 15:49:45 +08:00
    caocong
        1
    caocong  
       2022-12-06 14:03:14 +08:00
    ubuntu:latest

    ubuntu:latest
    slove
        2
    slove  
    OP
       2022-12-06 14:04:44 +08:00 via iPhone
    @caocong 英文标点符号我知道,这份是我手机打的
    lxzxl
        3
    lxzxl  
       2022-12-06 14:14:00 +08:00
    RUN alter user “root”@“localhost” identified with mysql_native_password by “12345”;

    你是想 shell 里面跑 sql?
    slove
        4
    slove  
    OP
       2022-12-06 14:24:07 +08:00 via iPhone
    @lxzxl 是的,不可以使用 mysql 语句吗
    lxzxl
        5
    lxzxl  
       2022-12-06 14:38:20 +08:00
    @slove #4 换个问法,你是想 bash 里面执行 sql?
    slove
        6
    slove  
    OP
       2022-12-06 14:46:21 +08:00 via iPhone
    @lxzxl 你的问法我理解,我在主机上敲 mysql ,直接进入 mysql ,所以可以执行 sql 语法,直到敲下 exit ,才算退出 mysql
    Dockerfile RUN mysql ,我理解就是在主机中启动 mysql ,然后进入数据库,后面的 sql 语句应该也是在数据库中执行,如果不是这样的,那 sql 语法应该写在哪里
    iyour
        7
    iyour  
       2022-12-06 14:46:25 +08:00
    用 chatgpt 试了一下,仅供参考
    [![ChatGPTaa6dca183f7b22f3.md.png]( https://img.picgo.net/2022/12/06/ChatGPTaa6dca183f7b22f3.md.png)]( https://www.picgo.net/image/Ul2mJ)
    kaedeair
        8
    kaedeair  
       2022-12-06 14:51:55 +08:00
    bash 里用 mysql 命令可以 RUN mysql < cmd1;cmd2;cmd3; 大概是这么做我没试过,也可能是 bash -c ""这种
    OP 的这种情景一般有两种变通方法
    1.用 docker-compose 拉别人的镜像组成服务群,加入环境变量来配置
    2.写一个 EntryPoint 脚本去判断是不是第一次运行
    Puteulanus
        9
    Puteulanus  
       2022-12-06 14:54:32 +08:00
    chloerei
        10
    chloerei  
       2022-12-06 14:54:37 +08:00   1
    @slove RUN 一条命令之后,相当于退出 shell ,下一条 RUN 是打开另一个 shell ,不会保留同一个会话。

    要执行 mysql 命令可以这样:

    ```
    RUN mysql -e "SQL"
    ```

    但是不建议这样做,容器内容是固化的,持久化数据应该放在 volume 。对应数据库就是它的 data 目录要挂到 volume ,这样在 dockerfile 里面执行的 sql 语句会被清空。

    而且不建议一个容器启动多个服务进程。

    建议先学习 docker 的基本概念,它不是虚拟机。
    slove
        11
    slove  
    OP
       2022-12-06 14:55:25 +08:00 via iPhone
    @iyour 我回头试下,感谢
    Mindzy
        12
    Mindzy  
       2022-12-06 14:57:44 +08:00
    建议所有 SQL 指令用 ENTRYPOINT 运行个 sh 执行
        13
    hefish  
       2022-12-06 14:58:52 +08:00   3
    这个不应该从 ubuntu:latest 开始构建。
    个人认为 docker 和微服务是相辅相成的。 相应的应用,也应该微服务化。OP 的这些应用至少可以分成三个服务。
    一个 mysql 服务,一个 php-fpm+httpd 服务。分两个容器跑,相互调用。 而不是在一个容器里跑三个服务。

    mysql 的服务,可以基于 mysql:8 来构建,具体可以参考 hub.docker.com 上的文档,用环境变量来指定默认的 root 密码。
    php-fpm 和 httpd 服务,可以基于 ubuntu:latest ,但容器里不能把进程跑在后台,要跑在前台,否则容器会自动退出。所以一般我喜欢是用 nginx 作 httpd ,然后用 supervised 来管理 php-fpm 和 nginx 两个服务,具体可以查询 supervised 相应的用法,配置文件还是比较简单的。

    做好容器之后,具体的应用数据,应该是在创建容器的时候,挂到容器里去,这样在容器销毁之后,数据可以保留下来。

    大致先讲这么多。
    hefish
    starqoq
        14
    starqoq  
       2022-12-06 15:01:56 +08:00   1
    1. Always combine RUN apt-get update with apt-get install in the same RUN statement.
    Best practices for writing Dockerfiles
    https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

    For example:
    RUN apt-get update && apt-get install -y \
    package-bar \
    package-baz \
    package-foo \
    && rm -rf /var/lib/apt/lists/*
    Using apt-get update alone in a RUN statement causes caching issues and subsequent apt-get install instructions fail.

    2. 数据库应该和 docker layout 分开,新建用户之类的操作,应该在 enterpoint.sh 里面进行

    3. 如果你真的特别想在 mysql 里面执行应该这样
    RUN echo "CMD1 \n CMD2\n CMD3\n" | mysql
    把 CMD1~3 发送到 mysql 的输入里执行

    RUN 命令是执行 elf 而不是在终端里输入然后回车。你可以认为每句话都在一个新的终端里执行
    slove
        15
    slove  
    OP
       2022-12-06 15:03:32 +08:00 via iPhone
    @kaedeair 感觉你说的应该可以执行,我回头测试下
    slove
        16
    slove  
    OP
       2022-12-06 15:08:26 +08:00 via iPhone
    @Mindzy 自学的 docker ,对 Dockerfile 的语法理解还是不透彻,我看网上很多把 sql 语句单独写一个文件,回头参考下别人的 Dockerfile
    javalaw2010
        17
    javalaw2010  
       2022-12-06 15:10:10 +08:00
    添加一个环境变量,ENV DEBIAN_FROnTEND=noninteractive 以避免软件安装过程中的交互出现,apt 安装的时候添加-y 参数,同样为了避免交互安装时出现交互。安装包控制镜像大小的一些小技巧前面的大佬们说过了,当然如果你不希望 DEBIAN_FRONTEND 在容器运行时也存在的话,可以 RUN DEBIAN_FROnTEND=noninteractive apt install -y XXX 。此外 ADD 命令并不会自动解压缩远程的压缩包,你得手动解压一下,至于 mysql 的问题,前面各位大佬也都说过了
    slove
        18
    slove  
    OP
       2022-12-06 15:11:03 +08:00 via iPhone
    @hefish 讲的很细了,感谢
    zhenrong
        19
    zhenrong  
       2022-12-06 15:11:55 +08:00
    用这个校验: https://www.fromlatest.io
    shakaraka
        20
    shakaraka  
    PRO
       2022-12-06 15:12:11 +08:00
    这是把 docker 当虚拟机用了呀
    lxzxl
        21
    lxzxl  
       2022-12-06 15:13:44 +08:00
    slove
        22
    slove  
    OP
       2022-12-06 15:13:50 +08:00 via iPhone
    @Puteulanus
    a | b ,a 执行完结果扔给 b 执行,不知道我理解的对不对
    deplivesb
        23
    deplivesb  
       2022-12-06 15:31:48 +08:00
    你这个真把 docker 当成虚拟机用了,启动一个 ubuntu 系统,安装一个 Apache 再安装一个 MySQL ,你这个干啥呢?
    slove
        24
    slove  
    OP
       2022-12-06 15:33:25 +08:00 via iPhone
    @starqoq 感谢,虽然你说的很多不理解,感觉是大佬
    @zhenrong 感谢
    @wunonglin 学习环境,玩坏了,就直接删除,挺方便的
    @lxzxl 我再认真看文档去,感谢

    感谢以上所有人的回复,谢谢
    slove
        25
    slove  
    OP
       2022-12-06 15:34:36 +08:00 via iPhone
    @deplivesb 装个学习环境,玩坏了,就直接删库跑路,不会被抓,哈哈
    dier
        26
    dier  
       2022-12-06 16:35:03 +08:00   3
    你这个误区有点多,我一时不知道从哪讲起。既然你说想练习 Dockerfile 语法,那我先从 Docker 的理解说起
    Docker 推荐一个容器只运行一个服务,例如你这个环境的最优做法是 MySQL 服务构建一个镜像,Apache 服务再构建一个镜像。
    原因就是容器在运行时必须要有一个主服务进程在前台持续运行,一般建议这个进程就是容器要运行的服务进程。当这个服务的进程停止时,容器会以为这个服务运行结束,容器则结束运行退出。
    如果你在一个容器里运行了多个服务,比如 MySQL 和 Apache ,你以其中一个服务为主服务使其在前台运行,如果另外一个服务意外终止了,你排查时会发现这个容器的状态还是运行状态。就没办法从容器的状态直接判断出来服务是否正常(简单的比喻就是你明明结束了 MySQL 的进程,但用其它命令查看 MySQL 端口发现它还在监听,你觉得是还在运行还是已经结束了?)。因为容器在运行时,你从外部是不容易观察到容器内的运行情况。

    再说 Dockerfile;
    用再说 Dockerfile 构建镜像时,Dockerfile 中的每个以大写开头的 FROM\RUN\ADD\COPY\CMD 都会像是一层饼,如果你要通过 RUN 做一些操作,就尽量写在这一个 RUN 下,以减少镜像的层数,同时也能防止一个镜像最后体积变得很大。
    例如:
    ```shell
    RUN apt update && \
    apt install aptech curl bash && \
    rm /tmp/*.gz
    ```
    另外,练习 Dockerfile 可以到 hub.docker.com 上去看看一些服务官方的镜像。基本上都有附 Dockerfile 的 github 的地址。建议先基于官方的 Dockerfile 来改着试试理解怎么写 Dockerfile

    最后,Dockerfile 排错。在使用 docker build 构建时,你每写的一个大写开头的命令都是一层,会从上到下依次执行,如果哪一层有问题,会提示准确的行级信息来供你排查是哪些命令编写有问题。
    hsfzxjy
        27
    hsfzxjy  
       2022-12-06 16:46:06 +08:00 via Android
    建议先学 shell/bash 语法和相关知识,还是基础知识不够

    如果你写成 shell 脚本能跑通,那改成 Dockerfile 基本也可以
    slove
        28
    slove  
    OP
       2022-12-06 16:46:57 +08:00 via iPhone
    @dier 嗯嗯,你的回复对我帮助很大,谢谢
    dev436
        29
    dev436  
       2022-12-06 18:17:49 +08:00
    您好,您给出的 Dockerfile 中存在一些语法错误和书写不规范的问题。我尝试纠正这些问题,并给出修改后的 Dockerfile 内容:
    dev436
        30
    dev436  
       2022-12-06 18:18:04 +08:00
    # 基于 ubuntu 最新版镜像
    FROM ubuntu:latest

    # 更新安装包列表
    RUN apt update

    # 安装 apache2
    RUN apt install -y apache2

    # 安装 mysql-server
    RUN apt install -y mysql-server

    # 启动 mysql
    RUN service mysql start

    # 登录 mysql
    RUN mysql -u root

    # 修改 root 密码
    RUN alter user "root"@"localhost" identified with mysql_native_password by "12345";

    # root 密码生效
    RUN flush privileges;

    # 新建数据库
    RUN create database wordpress;

    # 新建用户
    RUN create user "solve"@"localhost" identified by "888888";

    # 配置数据库用户
    RUN grant all on wordpress.* to "solve"@"localhost" with grant option;

    # 配置生效
    RUN flush privileges;

    # 退出数据库
    RUN exit

    # 下载 wordpress 最新版到指定 /var/www/html/
    ADD https://cn.wordpress.org/latest-zh_CN.tar.gz /var/www/html

    # 开放端口号
    EXPOSE 80

    CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
    slove
        31
    slove  
    OP
       2022-12-06 19:17:07 +08:00
    @dev436 这语句到# 修改 root 密码 RUN alter user "root"@"localhost" identified with mysql_native_password by "12345";就不行了。二楼说的对,RUN 命令执行完就结束了,sql 命令没在 mysql 里执行,网上搜了下,基本是单独做个 shell 脚本,引入 sql 语句,再执行数据库操作。
    有没有大佬知道单独语句怎么写,这样写不知对不对:RUN /bin/sh -c mysql -uroot <"alter user "root"@"localhost" identified with mysql_native_password by "12345"";
    g001
        32
    g001  
       2022-12-06 20:41:47 +08:00
    FROM ubuntu:latest:您在使用 : 分隔镜像名称和标签时,应该使用英文的冒号而不是中文的冒号。正确的语法应该是 FROM ubuntu:latest 。
    alter user “root”@“localhost”:您在使用字符串时,应该使用英文的双引号而不是中文的双引号。正确的语法应该是 alter user "root"@"localhost"。
    mysql_native_password by “12345”;:您在定义密码时,应该使用英文的双引号而不是中文的双引号。正确的语法应该是 mysql_native_password by "12345"
    slove
        33
    slove  
    OP
       2022-12-06 21:13:26 +08:00
    @g001 中英文是我在车上手机编辑的,主要问题不在这里,我的意思还是在 Dockerfile 里使用 sql 命令创建和修改用户权限
    slove
        34
    slove  
    OP
       2022-12-07 20:54:30 +08:00
    https://ibb.co/t8vMj7b
    https://ibb.co/4tswdv8
    https://ibb.co/WyLyQN7
    我把代码用这种方式重新写了,大佬帮忙看下,可有问题,抱拳感谢
    slove
        37
    slove  
    OP
       2022-12-07 21:14:44 +08:00
    不会贴图
    ---------Dockerfile--------------
    FROM ubuntu:latest
    COPY run.sh /root/test/run.sh
    COPY my.sql /root/test/my.sql
    RUN apt update
    RUN apt install mysql-server -y
    EXPOSE 3306
    CMD ["sh", "/root/test/run.sh"]


    ---------run.sh--------------
    #!bin/bash
    #查看 mysql 运行状态
    echo '1.查看 mysql 服务状态...'
    service mysql status
    echo '2.启动 mysql 服务...'
    service mysql start
    echo '3.导入 sql 命令...'
    mysql < /root/test/my.sql
    echo '4.执行完毕...'
    ---------my.sql--------------
    use mysql;
    #修改 root 密码
    alter user 'root'@'localhost' identified with mysql_native_password by '123456';
    #创建数据库 wordpress
    create database Wordpress;
    #创建用户 slove
    create user 'slove'@'localhost' identified by '888888';
    #设置 wordpress 数据库用户
    grant all on wordpress.* to 'slove'@'localhost' with grant option;
    #配置生效
    flush privileges;
    qq296015668
        38
    qq296015668  
       2023-03-02 15:49:45 +08:00
    简单的看了下,按照 op 给出的部分代码,简单的给出大致样本,但是有几个问题需要解决
    1. `service mysql start` 这条命令无法在构建是启动
    2. 缺少 `php` 依赖,就算构建成功也无法访问 wordpress
    3. 就算补全了 `php` 相关依赖,apache2 也缺少配置

    总之,只能给出一个大致的样本供参考。另外 `wordpress` 有 [官方镜像]( https://hub.docker.com/_/wordpress)


    ```Dockerfile

    FROM ubuntu:22.04

    ARG MYSQL_ROOT_PASSWORD 12345
    ARG DB_PASSWORD 888888

    ARG DEPENDENCIES=" \
    apache2 \
    mysql-server \
    wget"

    RUN apt-get update && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    apt-get install -y --no-install-recommends ${DEPENDENCIES} && \
    rm -rf /var/lib/apt/lists/*

    RUN service mysql start # 无法执行成功

    RUN mysql -uroot -e "\
    create database wordoress; \
    create user 'solve'@'localhost' identufied by '${DB_PASSWORD}'; \
    grant all on wordoress.* to 'solve'@'localhost'; \
    alter user 'root'@'localhost' identified with mysql_native_password by '${MYSQL_ROOT_PASSWORD}'; \
    flush privileges;"

    WORKDIR /var/www/html
    RUN wget https://cn.wordpress.org/latest-zh_CN.tar.gz && \
    tar -xf latest-zh_CN.tar.gz \
    rm -f latest-zh_CN.tar.gz

    EXPOSE 80
    CMD ["/bin/bash"]
    ```
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2825 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 13:32 PVG 21:32 LAX 06:32 JFK 09:32
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86