如何将docker日志重定向到单个文件?

时间:2016-12-14 14:05:19

标签: logging docker

我想将docker容器的所有日志重定向到单个日志文件以进行分析。我试过了

docker logs container > /tmp/stdout.log 2>/tmp/stderr.log

但是这会给两个不同的文件登录。我已经尝试了

docker logs container > /tmp/stdout.log

但它不起作用。

11 个答案:

答案 0 :(得分:87)

这个选项怎么样:

docker logs containername >& logs/myFile.log

它不会重定向问题中要求的日志,而是将它们复制一次到特定文件。

答案 1 :(得分:84)

无需重定向日志。

默认情况下,Docker将日志存储到一个日志文件中。要检查日志文件路径运行命令:

docker inspect --format='{{.LogPath}}' containername

/var/lib/docker/containers/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334-json.log

打开该日志文件并进行分析。

如果您重定向日志,那么您只会在重定向之前获取日志。你将无法看到实时日志。

修改

要查看实时日志,您可以在命令

下运行
tail -f `docker inspect --format='{{.LogPath}}' containername`

注意:

仅当docker生成日志(如果没有日志)时才会创建此日志文件/var/lib/docker/containers/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334-json.log,此文件将不存在。如果我们运行命令docker logs containername并且它什么都不返回,它就像某些时候类似。在这种情况下,此文件将不可用。

答案 2 :(得分:15)

docker logs -f <yourContainer> &> your.log &

说明:

  • -f(即--follow):写入所有现有日志并继续(跟随)记录下一步的所有内容。
  • &>重定向标准输出和标准错误。
  • 您可能希望在后台运行该方法,即&
  • 您可以按以下方式分隔输出和stderr:> output.log 2> error.log(而不是使用&>)。

答案 3 :(得分:4)

假设您有多个容器并且想要将日志聚合到一个文件中,则需要使用一些日志聚合器,如fluentd。支持fluentd作为docker容器的日志记录驱动程序。

所以在docker-compose中,你需要定义日志记录驱动程序

  service1:
    image: webapp:0.0.1
    logging:
      driver: "fluentd"
      options:
        tag: service1 

  service2:
        image: myapp:0.0.1
        logging:
          driver: "fluentd"
          options:
            tag: service2

第二步是更新流利的conf以满足服务1和服务2的日志

 <match service1>
   @type copy
   <store>
    @type file
    path /fluentd/log/service/service.*.log
    time_slice_format %Y%m%d
    time_slice_wait 10m
    time_format %Y%m%dT%H%M%S%z
  </store>
 </match> 
 <match service2>
    @type copy
   <store>
    @type file
    path /fluentd/log/service/service.*.log
    time_slice_format %Y%m%d
    time_slice_wait 10m
    time_format %Y%m%dT%H%M%S%
  </store>
 </match> 

在此配置中,我们要求将日志写入此路径的单个文件中 /fluentd/log/service/service.*.log

第三步是运行自定义的fluentd,它将开始将日志写入文件。

以下是link for step by step instructions

Bit Long,但正确的方法,因为您可以更好地控制日志文件路径等,并且它在Docker Swarm中运行良好。

答案 4 :(得分:2)

要将stdout和stderr都从Docker容器捕获到单个日志文件中,请运行以下命令:

docker logs container > container.log 2>&1

答案 5 :(得分:1)

首先检查您的容器ID

docker ps -a

您可以在“容器ID”列中看到第一行。 可能看起来像这样的“ 3fd0bfce2806” 然后在shell中键入

docker inspect --format='{{.LogPath}}' 3fd0bfce2806

您会看到类似

/var/lib/docker/containers/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1-json.log

然后您可以将其视为

cat /var/lib/docker/containers/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1-json.log

它将是JSON格式,您可以使用时间戳来跟踪错误

答案 6 :(得分:0)

Bash脚本可将所有容器日志复制到指定目录:

 // My classes here 

[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "MesWCF.IService")]
public interface IService
{
   //My methods here - example bellow

    //Example of one methods (collapsed above for brevity)
    [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/GetUserAccount", ReplyAction = "http://tempuri.org/IService/GetUserAccountResponse")]
    System.Threading.Tasks.Task<MesWCF.FraMesUser> GetUserAccountAsync(string name, string password);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
public interface IServiceChannel : MesWCF.IService, System.ServiceModel.IClientChannel
{
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
public partial class ServiceClient : System.ServiceModel.ClientBase<MesWCF.IService>, MesWCF.IService
{

    /// <summary>
    /// Implement this partial method to configure the service endpoint.
    /// </summary>
    /// <param name="serviceEndpoint">The endpoint to configure</param>
    /// <param name="clientCredentials">The client credentials</param>
    static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);

    public ServiceClient() :
            base(ServiceClient.GetDefaultBinding(), ServiceClient.GetDefaultEndpointAddress())
    {
        this.Endpoint.Name = EndpointConfiguration.BasicHttpBinding_IService.ToString();
        ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
    }

    public ServiceClient(EndpointConfiguration endpointConfiguration) :
            base(ServiceClient.GetBindingForEndpoint(endpointConfiguration), ServiceClient.GetEndpointAddress(endpointConfiguration))
    {
        this.Endpoint.Name = endpointConfiguration.ToString();
        ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
    }

    public ServiceClient(EndpointConfiguration endpointConfiguration, string remoteAddress) :
            base(ServiceClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
    {
        this.Endpoint.Name = endpointConfiguration.ToString();
        ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
    }

    public ServiceClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
            base(ServiceClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
    {
        this.Endpoint.Name = endpointConfiguration.ToString();
        ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
    }

    public ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
    {
    }

  //Methods here 

  //Example of one method (collapsed above for brevity)
    public System.Threading.Tasks.Task<MesWCF.FraMesUser> GetUserAccountAsync(string name, string password)
    {
        return base.Channel.GetUserAccountAsync(name, password);
    }
    public virtual System.Threading.Tasks.Task OpenAsync()
    {
        return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
    }

    public virtual System.Threading.Tasks.Task CloseAsync()
    {
        return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
    }

    private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
    {
        if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IService))
        {
            System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
            result.MaxBufferSize = int.MaxValue;
            result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            result.MaxReceivedMessageSize = int.MaxValue;
            result.AllowCookies = true;
            return result;
        }
        throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
    }

    private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
    {
        if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IService))
        {
            return new System.ServiceModel.EndpointAddress("http://10.208.132.246:12345/Service.svc");
        }
        throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
    }

    private static System.ServiceModel.Channels.Binding GetDefaultBinding()
    {
        return ServiceClient.GetBindingForEndpoint(EndpointConfiguration.BasicHttpBinding_IService);
    }

    private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
    {
        return ServiceClient.GetEndpointAddress(EndpointConfiguration.BasicHttpBinding_IService);
    }

    public enum EndpointConfiguration
    {

        BasicHttpBinding_IService,
    }
}
}

答案 7 :(得分:0)

由于Docker为我们合并了stdout和stderr,因此我们可以将日志输出与其他任何shell流一样对待。要将当前日志重定向到文件,请使用重定向运算符

$ docker logs test_container > output.log
 docker logs -f test_container > output.log

您无需将输出发送到stderr和stdout,而是将应用程序的输出重定向到文件,然后将文件映射到容器外部的永久存储。

$ docker logs test_container> /tmp/output.log

Docker不会在命令行上接受相对路径,因此,如果要使用其他目录,则需要使用完整路径。

答案 8 :(得分:0)

如果您在Windows上工作并且使用PowerShell(像我一样),则可以使用以下行捕获l=["a","d","a","d"] stdout

stderr

我希望它可以帮助某人!

答案 9 :(得分:0)

最简单的方法是在终端上使用以下命令:

docker logs elk > /home/Desktop/output.log

结构为:

docker logs <Container Name> > path/filename.log

答案 10 :(得分:0)

docker日志-f docker_container_name >> YOUR_LOG_PATH 2>&1&