基于docker封装个圣诞树

Docker镜像构建是通过 Dockerfile来构建的,里面运行的程序是可以自定的,从编写程序到安装Docker镜像,可以一气呵成。

使用docker搭建个圣诞树,最主要的是轻量化,如果是基于Linux系统搭建的话,下载镜像的几百兆就需要浪费很多时间,就失去了趣味性。

圣诞树的c++程序并不是我自己写的,我只是使用docker封装一下,感谢大佬提供的圣诞树程序。

 

g++编译C++代码,生成 Static Binaries,随后使用docker封装

1. 建立文件夹,用来存放代码

mkdir tree && cd tree/

 

2. 使用vim创建文件tree.cpp、xtree.txt

// tree.cpp

// Copyright (c) 2018 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)


// TODO:
//  * clean up the mess in code
//  * clean up after the cleanup
//  * add falling snow or glowing stars
//  * more modes for lamps

#include <cstdlib>
#include <chrono>
#include <thread>
#include <iostream>
#include <random>
#include <iterator>
#include <fstream>
#include <algorithm>
#include <atomic>

enum class color_t : unsigned char {};
constexpr color_t operator"" _c(unsigned long long int v) { return color_t(v); }

std::ostream& operator<< (std::ostream& os, color_t val) {
  return os << "\033[38;5;" << static_cast<int>(val) << 'm';
}

struct green_state {
  color_t color() const {
    return *(std::min(std::begin(kGreenColors) + dark, std::end(kGreenColors) - 1));
  }

  void increase_darkness() { ++dark; }
  void reset_darkness() { dark = 0; }

private:
  constexpr static color_t kGreenColors[] = { 22_c, 22_c, 28_c, 28_c, 34_c };
  int dark = 0;
};

struct lamps {
  void operator()(char c) {
    if (mode % max_state == 0)
      new_color();
    std::cout << col << c;
  }

  void end_cycle() {
    if (mode % max_state == 1) {
      new_color();
    } else if (mode % max_state == 2) {
      auto i = static_cast<int>(col);
      ++i;

      i %= 226;
      i = std::clamp(i, 154, 226);

      //i %= 202;
      //i = std::clamp(i, 196, 202);
      col = static_cast<color_t>(i);
    }
  }

  void change_mode() {
    ++mode;
  }

  void stop() {
    stopped = true;
  }

  bool was_stopped() {
    return stopped;
  }

private:
  void new_color() {
    std::sample(std::begin(kPrettyColors), std::end(kPrettyColors), &col, 1, rand);
  }

  std::atomic<bool> stopped = false;
  std::atomic<size_t> mode{0};
  static constexpr size_t max_state = 3;
  std::mt19937 rand{std::random_device{}()};
  color_t col = 0_c;

  // https://misc.flogisoft.com/bash/tip_colors_and_formatting
  static constexpr color_t kPrettyColors[] = {
    1_c, 9_c, 11_c, 15_c, 45_c, 87_c, 118_c, 154_c, 155_c, 165_c, 193_c, 196_c, 198_c,208_c, 226_c, 15_c
  };
};

std::string get_tree(int args, const char** argv) {
  std::string filename = "xtree.txt";
  if (args > 1) {
    filename = argv[1];
  }

  std::string tree;
  std::ifstream ifs{filename.c_str()};
  std::getline(ifs, tree, '\0');
  return tree;
}

int main(int args, const char** argv) {
  using namespace std::literals::chrono_literals;

  auto tree = get_tree(args, argv);
  lamps lamp;

  std::thread t([&lamp]() {
    char c;
    while (std::cin >> c) {
      if (c == 'q') {
        lamp.stop();
        break;
      }
      lamp.change_mode();
    }
  });

  for (;;) {
    if (lamp.was_stopped()) {
      break;
    }

    std::system("clear");

    green_state g;
    auto it = tree.begin();
    auto end = tree.end();
    auto prev_width = 0;
    for (; it != end; ++it) {
      const auto c = *it;
      switch (c) {
      case '*': [[fall_through]]
      case ' ':
        std::cout << g.color() << c;
        break;

      case 'o': [[fall_through]]
      case 'O':
        lamp(c);
        break;

      case '#':
        std::cout << 94_c << c;
        break;

      case '\n': {
          const auto next_new_line = std::find(it + 1, end, '\n');
          const auto new_width = std::count_if(
              it,
              next_new_line,
              [](char s) { return s == '*' || s == 'o' || s == 'O'; }
          );
          if (prev_width < new_width) {
            g.increase_darkness();
          } else {
            g.reset_darkness();
          }
          prev_width = new_width;
        }
        [[fall_through]]

      default:
        std::cout << 0_c << c;
      }
    }

    std::cout << 0_c << std::endl;
    lamp.end_cycle();
    std::this_thread::sleep_for(400ms);
  }

  t.join();
}

 下面为xtree.txt文件

                                                 
                       O                         
                      ***                        
                     **O**                       
                    *******                      
                   *********                     
                  ***********                   
                   ******o**                     
                  ***********                    
                 ****o********                   
                ***************                  
               ****o***o********                 
              *******************                
            ***********************              
               *****O***********                 
              **********o********                
             ****************o****               
            **O********************              
           ***********o********O****             
         *****************************           
             *********************               
            ***o*******************              
           ***********o*******o*****             
          ***************************            
         ***********************O*****           
        ***O***************************          
      ***********************************        
           *************************             
          *******o********o**********            
         *****************************           
        **************o****************          
       *************************O*******         
      *****O*****************************        
    **************o************************      
          ***************************            
         *************o***************           
        ***********o*******************          
       **************************O******         
      ***o******************O************        
    ***o***********o****************o******      
                      ###                        
                      ###                        
                      ###                        
                  ###########                    
                  ###########                    

3. 生成静态可执行文件,至于为什么要建立静态链接请自行Google。

g++-7 -O2 -o tree tree.cpp -static -std=c++17 -pthread

 此时就会有 tree 文件,执行 tree 文件就可以看到圣诞树。

4. 建立Dockerfile文件

vim Dockerfile
FROM scratch
ADD tree /
ADD xtree.txt /
CMD ["/tree"]

 5. 生成docker镜像

docker build -t walker519/merry-christmas .

 

6. 可以使用下面指令运行镜像

docker run walker519/merry-christmas

 

reference:

  1. https://github.com/apolukhin/christmas-tree
  2. https://www.ianlewis.org/en/creating-smaller-docker-images-static-binaries
  3.  

 

如果有什么错误,欢迎各位留言批评指正。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值