Como todos já
ouviram , no final de maio, o Telegram lançou o servidor oficial MTProto Proxy (também conhecido como MTProxy), escrito no
seguinte idioma . Em 2018, não há muito onde sem o Docker, porque é acompanhado pela mesma maneira "oficial" no formato de configuração zero. Tudo ficaria bem, mas três "buts" estragaram um pouco a impressão do lançamento: a imagem pesa> 130 Mb (existe um Debian bastante rechonchudo, não o Alpine usual), devido ao "zero-config" nem sempre é convenientemente configurado (apenas pelas configurações do ambiente) e os caras esqueceram a campanha, esquematizaram o Dockerfile.
TL; DR Criaremos uma imagem de docker praticamente alpina oficial 1 em 1 de 5,94 MB de tamanho e a colocaremos
aqui (e o Dockerfile
aqui ); ao longo do caminho, descobriremos como às vezes você pode fazer amizade com o software Alpine usando pinças e um arquivo, e teremos um pouco de tamanho, exclusivamente por diversão.
Conteúdo da imagem
Mais uma vez, por que toda essa confusão? Vamos ver o que a imagem oficial representa com o comando
history :
$ docker history --no-trunc --format "{{.Size}}\t{{.CreatedBy}}" telegrammessenger/proxy
As camadas são lidas de baixo para cima, respectivamente:

A mais grossa é a Debian Jessie, da qual a imagem original é herdada. Temos que nos livrar dela antes de tudo (alpine: 3.6, para comparação, pesa 3.97MB); seguidos por dimensões são curl e certificados novos. Para entender o que os outros dois arquivos e o diretório significam, examinaremos o interior usando o comando
run , substituindo o CMD pelo bash (isso permitirá que você percorra a imagem lançada, se conheça mais de perto, execute certos fragmentos, copie algo útil):
$ docker run -it --rm telegrammessenger/proxy /bin/bash
Agora podemos restaurar facilmente a imagem do incidente - algo como o Dockerfile oficial perdido parecia:
FROM debian:jessie-20180312 RUN set -eux \ && apt-get update \ && apt-get install -y --no-install-recommends curl ca-certificates \ && rm -rf /var/lib/apt/lists/* COPY ./mtproto-proxy /usr/local/bin RUN mkdir /data COPY ./secret/ /etc/telegram/ COPY ./run.sh /run.sh CMD ["/bin/sh", "-c", "/bin/bash /run.sh"]
Onde mtproto-proxy é um servidor compilado, a pasta secreta contém apenas o arquivo hello-explorers-how-you-doing com a chave de criptografia AES (consulte os comandos do servidor, aliás, há uma recomendação oficial para obter a chave pela API, mas coloque-a assim) provavelmente para evitar a situação em que a API também está bloqueada) e o run.sh faz todos os preparativos para iniciar o proxy.
O conteúdo do run.sh original Assembléia
No CentOS 7 MTProxy em Habré já
coletado , tentaremos coletar uma imagem no Alpine e economizar megabytes, comerciais, 130 na imagem do docker resultante.
Uma característica distintiva do Alpine Linux é o uso de musl em vez de glibc. Ambas são bibliotecas C padrão. Musl é pequeno (não possui um quinto do "padrão"), mas volume e desempenho (prometidos pelo menos) decidem quando se trata do Docker. E colocar glibc no Alpine não é racialmente correto, o tio Jakub Jirutka
não entenderá , por exemplo.
Também criaremos docker para isolar dependências e obter liberdade para experimentação; portanto, crie um novo Dockerfile:
FROM alpine:3.6 RUN apk add --no-cache git make gcc musl-dev linux-headers openssl-dev RUN git clone --single-branch --depth 1 https://github.com/TelegramMessenger/MTProxy.git /mtproxy/sources RUN cd /mtproxy/sources \ && make -j$(getconf _NPROCESSORS_ONLN)
Das dependências, o git será útil (e não apenas para clonar o repositório oficial, o arquivo make anexará o sha commit à versão), make, gcc e arquivos de cabeçalho (o conjunto mínimo foi obtido empiricamente). Apenas clonamos o ramo principal com uma profundidade de 1 confirmação (definitivamente não precisamos de histórico). Bem, vamos tentar utilizar todos os recursos do host ao compilar com a opção -j. Eu o dividi deliberadamente em um número maior de camadas para obter um cache conveniente durante a reconstrução (geralmente existem muitas).
Executaremos o comando
build (estando no diretório com o Dockerfile):
$ docker build -t mtproxy:test .
E aqui está o primeiro problema:
In file included from ./net/net-connections.h:34:0, from mtproto/mtproto-config.c:44: ./jobs/jobs.h:234:23: error: field 'rand_data' has incomplete type struct drand48_data rand_data; ^~~~~~~~~
Na verdade, todos os subsequentes serão conectados a ele. Primeiro, para aqueles que não estão familiarizados, o compilador jura pela falta de uma declaração da estrutura drand48_data. Em segundo lugar, os desenvolvedores de musl obtiveram pontuação em funções aleatórias seguras para threads (com o _r postfix) e em tudo relacionado a elas (incluindo estruturas). E os desenvolvedores do Telegram, por sua vez, não se preocuparam em compilar para sistemas onde o random_r e suas contrapartes não são implementadas (em muitas bibliotecas de SO, você pode ver o sinalizador HAVE_RANDOM_R ou sua presença arbitrária ou presença ou ausência desse grupo de funções geralmente é levada em consideração no auto-configurador).
Bem, agora vamos definitivamente instalar o glibc? Não! Copiaremos o mínimo necessário do glibc e faremos um patch para as fontes MTProxy.
Além dos problemas com o random_r, pegamos um problema com a função backtrace (execinfo.h), que é usada para gerar o backtrace da pilha em caso de uma exceção: você pode tentar substituí-lo pela implementação do libunwind, mas não vale a pena, porque a chamada foi enquadrada pela verificação de __GLIBC__.
Conteúdo do patch Random_compat.patch Coloque-o na pasta ./patches e modifique um pouco o nosso Dockerfile para aplicar o patch rapidamente:
FROM alpine:3.6 COPY ./patches /mtproxy/patches RUN apk add --no-cache --virtual .build-deps \ git make gcc musl-dev linux-headers openssl-dev \ && git clone --single-branch --depth 1 https://github.com/TelegramMessenger/MTProxy.git /mtproxy/sources \ && cd /mtproxy/sources \ && patch -p0 -i /mtproxy/patches/randr_compat.patch \ && make -j$(getconf _NPROCESSORS_ONLN) \ && cp /mtproxy/sources/objs/bin/mtproto-proxy /mtproxy/ \ && rm -rf /mtproxy/{sources,patches} \ && apk add --no-cache --virtual .rundeps libcrypto1.0 \ && apk del .build-deps
Agora, o binário mtproto-proxy montado é pelo menos iniciado e podemos seguir em frente.
Liquidação
É hora de transformar o run.sh original em docker-entrypoint.sh. Na minha opinião, isso é lógico quando a "ligação obrigatória" entra em ENTRYPOINT (ela sempre pode ser sobrecarregada de fora), e os argumentos para iniciar o aplicativo dockerized se ajustam ao máximo em CMD (+ variáveis de ambiente como um subestudo).
Poderíamos instalar o bash e o grep completo em nossa imagem alpina (explicarei mais adiante) para evitar dores de cabeça e usar o código original como está, mas isso inflará nossa imagem em miniatura para desonrar, para que possamos cultivar um bonsai real, sua mãe.
Vamos começar com o shebang, substitua
#!/bin/bash
por
#!/bin/sh
. O padrão para as cinzas alpinas é capaz de digerir quase toda a sintaxe "como está" do bash, mas ainda encontramos um problema - por razões desconhecidas, ele se recusou a aceitar parênteses em uma das condições, portanto, expandimos invertendo a lógica de comparação:

Agora, estamos aguardando um confronto com grep, que na entrega do busybox é um pouco diferente do usual (e, a propósito, muito mais lento, lembre-se de seus projetos). Primeiro, ele não entende a expressão
{,15}
, ele precisará especificar explicitamente
{0,15}
. Em segundo lugar, ele não suporta o sinalizador
-P
(estilo perl), mas digere silenciosamente a expressão quando estendido (-E) está ativado.
O que resta em nossas dependências é apenas curl (não faz sentido substituí-lo pelo wget do busybox) e libcrypto (basta, o openssl em si não é necessário neste assembly).
Uma bela construção de
vários estágios apareceu no Docker há alguns anos; é ideal, por exemplo, para aplicativos Go ou para situações em que a montagem é complicada e mais fácil de transferir artefatos de imagem para imagem do que para fazer a limpeza final. Vamos usá-lo para plantar o nosso bonsai, isso vai economizar um pouco.
FROM alpine:3.6 # ( ) RUN apk add --no-cache --virtual .build-deps \ # ... , && make -j$(getconf _NPROCESSORS_ONLN) FROM alpine:3.6 # , , WORKDIR /mtproxy COPY --from=0 /mtproxy/sources/objs/bin/mtproto-proxy . # #
Os bonsais devem ser bonsais - livre-se da instalação da libcrypto. Ao compilar, precisávamos dos arquivos de cabeçalho do pacote openssl-dev, que nas dependências abrirão a libcrypto e nosso executável será orientado para o uso da libcrypto.so.1.0.0. Mas essa é a única dependência, além disso, é pré-instalada no Alpine (na versão 3.6, é libcrypto.so.41, 3.7 - libcrypto.so.42, está em / lib /). Eles me repreendem agora, essa não é a maneira mais confiável, mas vale a pena e ainda adicionamos um link simbólico à versão existente (se você tiver uma maneira melhor, aceitarei com prazer o PR).
Toques finais e resultado:
Hub DockerGithubFicaria muito grato por qualquer conselho e contribuição.