Tu aplicación C++ merece un mejor empaquetado: sumergámonos en Docker
\n\nEscribiste un excelente analizador en C++ que procesa gigabytes de registros a la velocidad del rayo. O quizás creaste un microservicio de alta carga para trabajar con sockets de red. El código está depurado, todo funciona. Pero llega el momento de la verdad: el despliegue. Y entonces comienza: «¿Qué versión de libcurl tienes?», «¿Por qué falló en producción con el error GLIBC?», «¿Por qué instalas todo GCC en el servidor?».
\n\n¿Te suena familiar? Bienvenido al mundo de la contenerización de aplicaciones C++ con Docker. Si hasta ahora pensabas que Docker era solo para JavaScript y Python, te estás perdiendo de mucho. En realidad, es precisamente para C++ donde la contenerización otorga un superpoder: obtienes un entorno inmutable donde el binario se compila una vez y funciona en todas partes, desde tu portátil hasta un clúster de producción.
\n\nEn este artículo no solo analizaremos la teoría. Vamos a paso a paso crear una aplicación C++, empaquetarla en Docker, optimizar la imagen al tamaño mínimo posible y hacer que el contenedor funcione como un reloj. ¡Allá vamos!
\n\n¿Por qué Docker es el mejor amigo del desarrollador C++?
\n\nMuchos creen que las aplicaciones C++ son fáciles de distribuir como binarios. Técnicamente, sí. Prácticamente, es un camino al infierno. Diferentes distribuciones de Linux, versiones de glibc, falta de bibliotecas, compatibilidad ABI rota: estos son solo algunos de los problemas.
\n\nDocker resuelve los tres principales dolores de cabeza del desarrollador C++:
\n\n- \n
- Reproducibilidad de la compilación: sabes exactamente qué versión del compilador, CMake, Boost y otras dependencias se utiliza. Nada de «en mi máquina funciona». \n
- Aislamiento: el contenedor no ensucia el sistema anfitrión. No es necesario instalar GCC en el servidor de producción; basta con un runtime mínimo. \n
- Escalabilidad: la imagen lista se puede levantar fácilmente en Kubernetes o Docker Swarm. C++ maneja muy bien la carga, y Docker ayuda a distribuir esa carga. \n
Y lo más importante: la contenerización de aplicaciones C++ no requiere magia. Todo lo que necesitas es Docker y un poco de paciencia.
\n\nCreando una aplicación C++ simple para contenerizar
\n\nComo ejemplo, no tomaremos un «¡Hola, Mundo!», sino algo más realista. Supongamos que estamos escribiendo un pequeño servidor HTTP en C++ usando Boost.Beast. Pero para no sobrecargar el artículo, haremos una versión simplificada: un servidor echo de sockets con la API POSIX pura. Esto mostrará cómo trabajar con dependencias del sistema.
\n\nArchivo server.cpp:
#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 // Crear socket\n if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {\n perror("socket failed");\n exit(EXIT_FAILURE);\n }\n\n // Vincular al puerto 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