Containerização de aplicações C++ com Docker: guia passo a passo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Sua aplicação C++ merece uma embalagem melhor: mergulhando no Docker

\n\n

Você escreveu um parser C++ incrível que processa gigabytes de logs em um piscar de olhos. Ou talvez tenha criado um microsserviço de alta carga para trabalhar com sockets de rede. O código está depurado, tudo voa. Mas chega o momento da verdade — o deploy. E então começa: "Qual versão do libcurl você está usando?", "Por que caiu em produção com erro GLIBC?", "Por que você está instalando o GCC inteiro no servidor?".

\n\n

Familiar? Bem-vindo ao mundo da containerização de aplicações C++ com Docker. Se você ainda pensava que Docker era só para JavaScript e Python, está perdendo muita coisa. Na verdade, é para C++ que a containerização dá um superpoder: você obtém um ambiente imutável, onde o binário é compilado uma vez e funciona em qualquer lugar — do seu notebook ao cluster de produção.

\n\n

Neste artigo, não vamos apenas abordar a teoria. Vamos passo a passo criar uma aplicação C++, empacotá-la no Docker, otimizar a imagem para o menor tamanho possível e fazer o contêiner funcionar como um relógio. Vamos lá!

\n\n

Por que Docker é o melhor amigo do desenvolvedor C++?

\n\n

Muitos acreditam que aplicações C++ são fáceis de distribuir como binários. Tecnicamente — sim. Na prática — é um caminho para o inferno. Diferentes distribuições Linux, versões do glibc, falta de bibliotecas, compatibilidade ABI quebrada — são apenas alguns dos problemas.

\n\n

Docker resolve três principais dores do desenvolvedor C++:

\n\n
    \n
  • Reprodutibilidade da compilação: você sabe exatamente qual versão do compilador, CMake, Boost e outras dependências está sendo usada. Nada de "funciona na minha máquina".
  • \n
  • Isolamento: o contêiner não polui o sistema host. Não é necessário instalar GCC no servidor de produção — apenas um runtime mínimo é suficiente.
  • \n
  • Escalabilidade: a imagem pronta é facilmente implantada no Kubernetes ou Docker Swarm. C++ lida muito bem com carga, e o Docker ajuda a distribuir essa carga.
  • \n
\n\n

E o principal — a containerização de aplicações C++ não requer mágica. Tudo que você precisa é do Docker e um pouco de paciência.

\n\n

Criando uma aplicação C++ simples para containerização

\n\n

Para o exemplo, não vamos usar "Hello, World!", mas algo mais realista. Suponha que estamos escrevendo um pequeno servidor HTTP em C++ usando Boost.Beast. Mas para não sobrecarregar o artigo, faremos uma versão simplificada — um servidor echo de socket usando a API POSIX pura. Isso mostrará como trabalhar com dependências do sistema.

\n\n

Arquivo server.cpp:

\n\n
#include <iostream>\n#include <string>\n#include <cstring>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <unistd.h>\n\nint main() {\n    int server_fd, new_socket;\n    struct sockaddr_in address;\n    int opt = 1;\n    int addrlen = sizeof(address);\n    char buffer[1024] = {0};\n\n    // Criando o socket\n    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {\n        perror("socket failed");\n        exit(EXIT_FAILURE);\n    }\n\n    // Vinculando à porta 8080\n    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {\n        perror("setsockopt");\n        exit(EXIT_FAILURE);\n    }\n    address.sin_family = AF_INET;\n    address.sin_addr.s_addr = INADDR_ANY;\n    address.sin_port = htons(8080);\n\n    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {\n        perror("bind failed");\n        exit(EXIT_FAILURE);\n    }\n\n    if (listen(server_fd, 3) < 0) {\n        perror("listen");\n        exit(EXIT_FAILURE);\n    }\n\n    std::cout << "Server listening on port 8080" << std::endl;\n\n    while (true) {\n        if ((new_socket = accept(server_fd, (struct sockaddr *)&address,\n                                 (socklen_t*)&addrlen)) < 0) {\n            perror("accept");\n            exit(EXIT_FAILURE);\n        }\n\n        read(new_socket, buffer, 1024);\n                

Blogs

Book Recommendations