首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >设备或资源从零开始在容器中繁忙和高寒,但不在ubuntu上。

设备或资源从零开始在容器中繁忙和高寒,但不在ubuntu上。
EN

Stack Overflow用户
提问于 2020-11-13 15:23:36
回答 1查看 1.5K关注 0票数 4

我编辑了这个问题,但我的问题出现在一个高山容器里。现在,我从零开始在容器中遇到了同样的问题。这是一个同样的问题,但范围缩小了一点。

正如标题所描述的,我在一个Ubuntu容器中有一个可执行文件,用于构建我的应用程序,但是一旦我将它复制到一个阿尔卑斯容器中,我就得到了具有相同可执行文件的Device or resource busy,我对正在发生的事情有点困惑。

这是我的文档:

代码语言:javascript
复制
ARG UBUNTU_VERSION=20.04
FROM ubuntu:${UBUNTU_VERSION} as builder

ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get -y install \
    curl \
    g++-10 \
    gcc-10 \
    ninja-build \
    unzip \
    zip \
    make \
    perl \
    pkg-config \
    git \
    gdb

RUN mkdir /opt/vcpkg \
    && curl -L -s "https://github.com/microsoft/vcpkg/tarball/8ce7b41302728ff6fc8bd377f572c4cbe8c64c1d" | tar --strip-components=1 -xz -C /opt/vcpkg \
    && /opt/vcpkg/bootstrap-vcpkg.sh

RUN mkdir /opt/cmake && \
    curl -s "https://cmake.org/files/v3.18/cmake-3.18.0-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C /opt/cmake

RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 && \
    update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10

ENV PATH="/opt/cmake/bin:/opt/vcpkg:${PATH}"

RUN mkdir /build2
COPY src2 /source/src2
WORKDIR /build2
RUN cmake /source/src2 \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_GENERATOR=Ninja \
    -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja \
    -DCMAKE_INSTALL_PREFIX=/install \
    -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake 
RUN cmake --build . --target all

FROM scratch

COPY --from=builder /build2/http-beast-ssl /http-beast-ssl
COPY --from=builder /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=builder /usr/lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/libdl.so.2
COPY --from=builder /usr/lib/x86_64-linux-gnu/libpthread.so.0 /usr/lib/x86_64-linux-gnu/libpthread.so.0
COPY --from=builder /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/x86_64-linux-gnu/libstdc++.so.6
COPY --from=builder /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
COPY --from=builder /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
COPY --from=builder /usr/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc.so.6
COPY --from=builder /usr/lib/x86_64-linux-gnu/libm.so.6 /usr/lib/x86_64-linux-gnu/libm.so.6
COPY --from=builder /usr/share/ca-certificates /usr/share/ca-certificates
COPY --from=builder /etc/ssl/ /etc/ssl/

ENTRYPOINT ["/http-beast-ssl"]

当我在ubuntu容器中运行http-beast-ssl example.com 443 /时,一切正常。我像预期的那样将HTML返回控制台。

当我从零开始在容器内做同样的事情时,我就会得到错误。

那是怎么回事,我该怎么解决呢?在我的容器中,是否有必要使网络按预期的方式工作呢?那里少了什么?

下面是作为参考的C++源代码:

代码语言:javascript
复制
#include <boost/asio/ssl.hpp>
#include <boost/lexical_cast.hpp>
#include <openssl/cryptoerr.h>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/error.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/beast/version.hpp>
#include <openssl/opensslv.h>
#include <cstdlib>
#include <iostream>
#include <string>

namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http;   // from <boost/beast/http.hpp>
namespace net = boost::asio;    // from <boost/asio.hpp>
namespace ssl = net::ssl;       // from <boost/asio/ssl.hpp>
using tcp = net::ip::tcp;       // from <boost/asio/ip/tcp.hpp>

// Performs an HTTP GET and prints the response
int main(int argc, char** argv)
{
    std::cout << OPENSSL_VERSION_TEXT << std::endl;
    try
    {
        // Check command line arguments.
        if(argc != 4 && argc != 5)
        {
            std::cerr <<
                "Usage: http-client-sync-ssl <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
                "Example:\n" <<
                "    http-client-sync-ssl www.example.com 443 /\n" <<
                "    http-client-sync-ssl www.example.com 443 / 1.0\n";
            return EXIT_FAILURE;
        }
        auto const host = argv[1];
        auto const port = argv[2];
        auto const target = argv[3];
        int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;

        // The io_context is required for all I/O
        net::io_context ioc;

        // The SSL context is required, and holds certificates
        ssl::context ctx(ssl::context::tlsv12_client);

        // This holds the root certificate used for verification
        ctx.set_default_verify_paths();

        // Verify the remote server's certificate
        ctx.set_verify_mode(ssl::verify_peer);

            // These objects perform our I/O
        tcp::resolver resolver(ioc);
        beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);

        // Set SNI Hostname (many hosts need this to handshake successfully)
        if(! SSL_set_tlsext_host_name(stream.native_handle(), host))
        {
            beast::error_code ec{static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()};
            throw beast::system_error{ec};
        }

        // Look up the domain name
        auto const results = resolver.resolve(host, port);

        // Make the connection on the IP address we get from a lookup
        beast::get_lowest_layer(stream).connect(results);

        // Perform the SSL handshake
        stream.handshake(ssl::stream_base::client);

        // Set up an HTTP GET request message
        http::request<http::string_body> req{http::verb::get, target, version};
        req.set(http::field::host, host);
        req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);

        // Send the HTTP request to the remote host
        http::write(stream, req);

        // This buffer is used for reading and must be persisted
        beast::flat_buffer buffer;

        // Declare a container to hold the response
        http::response<http::dynamic_body> res;

        // Receive the HTTP response
        http::read(stream, buffer, res);

        // Write the message to standard out
        std::cout << res << std::endl;

        // Gracefully close the stream
        beast::error_code ec;
        stream.shutdown(ec);
        if(ec == net::error::eof)
        {
            // Rationale:
            // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
            ec = {};
        }
        if(ec)
            throw beast::system_error{ec};

        // If we get here then the connection is closed gracefully
    }
    catch(boost::system::system_error const& e)
    {
        auto const& error = e.code();
        std::string err = error.message();
        if (error.category() == boost::asio::error::get_ssl_category()) {
            err = std::string(" (")
                +boost::lexical_cast<std::string>(ERR_GET_LIB(error.value()))+","
                +boost::lexical_cast<std::string>(ERR_GET_FUNC(error.value()))+","
                +boost::lexical_cast<std::string>(ERR_GET_REASON(error.value()))+") ";
    
            //ERR_PACK /* crypto/err/err.h */
            char buf[128];
            ::ERR_error_string_n(error.value(), buf, sizeof(buf));
            err += buf;
            std::cerr << err << std::endl;
        } else {
            std::cerr << err << std::endl;
        }
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
    
}

这是我的vcpkg.jsonCMakeLists.txt文件:

代码语言:javascript
复制
{
    "name": "mypackage",
    "version-string": "0.1.0-dev",
    "dependencies": [
        "boost-asio",
        "boost-beast",
        "openssl"
    ]
}
代码语言:javascript
复制
cmake_minimum_required(VERSION 3.18)
project(beast-test)

set(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY ON)
set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH OFF)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
set(CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH OFF)

find_package(Boost 1.74 REQUIRED COMPONENTS system)
find_package(Threads REQUIRED)
find_package(OpenSSL REQUIRED)

add_executable(http-beast-ssl main2.cpp)
target_link_libraries(http-beast-ssl PRIVATE Threads::Threads Boost::system OpenSSL::SSL OpenSSL::Crypto)

一开始,我在一个高寒容器中遇到了同样的问题,即使使用静态链接编译,也会出现这个问题。

当在高寒容器中运行curl https://example.com时,它可以正常工作,但我的应用程序仍然无法发出http请求。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-18 22:33:58

我知道错误消息显示了一些完全无关的东西,但是这里的问题(和往常一样)是缺少库。添加以下行以包括DNS库:

代码语言:javascript
复制
COPY --from=builder /usr/lib/x86_64-linux-gnu/libnss_dns.so.2 /usr/lib/x86_64-linux-gnu/libnss_dns.so.2
COPY --from=builder /usr/lib/x86_64-linux-gnu/libresolv.so.2 /usr/lib/x86_64-linux-gnu/libresolv.so.2

这有点像一个常见的陷阱与划痕。我建议您在开发和测试映像时添加所有库,然后重写Dockerfile,只留下必要的库。这样更容易发现你忘了什么东西。

更新

我通过将所有库从构建器步骤(Ubuntu)复制到本地计算机(./libs)并将它们安装到最终(划痕)步骤来调试这个过程:

代码语言:javascript
复制
version: "3.7"

services:
  test:
    build:
      context: .
    volumes:
    - ./libs:/usr/lib/x86_64-linux-gnu

从那以后,它立即开始工作。因此,我开始逐个删除复制的库,直到图像再次被破坏。我就是这样找到所需的库的。我确信一定有更好的方法来做到这一点,我只是不熟悉C++。

全Dockerfile

代码语言:javascript
复制
ARG UBUNTU_VERSION=20.04
FROM ubuntu:${UBUNTU_VERSION} as builder

ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get -y install \
    curl \
    g++-10 \
    gcc-10 \
    ninja-build \
    unzip \
    zip \
    make \
    perl \
    pkg-config \
    git \
    gdb

RUN mkdir /opt/vcpkg \
    && curl -L -s "https://github.com/microsoft/vcpkg/tarball/8ce7b41302728ff6fc8bd377f572c4cbe8c64c1d" | tar --strip-components=1 -xz -C /opt/vcpkg \
    && /opt/vcpkg/bootstrap-vcpkg.sh

RUN mkdir /opt/cmake && \
    curl -s "https://cmake.org/files/v3.18/cmake-3.18.0-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C /opt/cmake

RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 && \
    update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10

ENV PATH="/opt/cmake/bin:/opt/vcpkg:${PATH}"

RUN mkdir /build2
COPY src /source/src
WORKDIR /build2
RUN cmake /source/src \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_GENERATOR=Ninja \
    -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja \
    -DCMAKE_INSTALL_PREFIX=/install \
    -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake
RUN cmake --build . --target all

FROM scratch

COPY --from=builder /build2/http-beast-ssl /http-beast-ssl
COPY --from=builder /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=builder /usr/lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/libdl.so.2
COPY --from=builder /usr/lib/x86_64-linux-gnu/libpthread.so.0 /usr/lib/x86_64-linux-gnu/libpthread.so.0
COPY --from=builder /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/x86_64-linux-gnu/libstdc++.so.6
COPY --from=builder /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28
COPY --from=builder /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
COPY --from=builder /usr/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc.so.6
COPY --from=builder /usr/lib/x86_64-linux-gnu/libm.so.6 /usr/lib/x86_64-linux-gnu/libm.so.6
COPY --from=builder /usr/lib/x86_64-linux-gnu/libnss_dns.so.2 /usr/lib/x86_64-linux-gnu/libnss_dns.so.2
COPY --from=builder /usr/lib/x86_64-linux-gnu/libresolv.so.2 /usr/lib/x86_64-linux-gnu/libresolv.so.2
COPY --from=builder /usr/share/ca-certificates /usr/share/ca-certificates
COPY --from=builder /etc/ssl/ /etc/ssl/

ENTRYPOINT ["/http-beast-ssl"]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64823495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档