我已经正确更改了docker容器的时区。我是否需要在docker容器中安装NTP服务器以定期同步时间,或者容器是否会从主机同步时间?
答案 0 :(得分:101)
如果您在OSX上运行boot2docker,请参阅此问题:https://github.com/boot2docker/boot2docker/issues/290
时间同步成为一个问题,因为boot2docker主机在您的操作系统处于睡眠状态时会有时间漂移。使用-v /etc/localtime:/etc/localtime:ro
相反,现在,你必须在OSX上定期运行它:
/usr/local/bin/boot2docker ssh sudo ntpclient -s -h pool.ntp.org
Kitematic用户的更新
如果您正在运行Kitematic,这是在OSX中启动和运行Docker的建议机制,则必须定期运行此命令:
docker-machine ssh default 'sudo ntpclient -s -h pool.ntp.org'
或者,对于旧版本的docker
docker-machine ssh dev 'sudo ntpclient -s -h pool.ntp.org'
针对OSX的新原生Docker用户的更新
新的Docker Beta取消了VirtualBox和Docker Machine。 Docker的最新版本(目前,1.12.1-beta25(版本:11807))似乎能够检测何时出现时间不连续并进行相应调整。因此,这应该不再是一个问题......万岁!
答案 1 :(得分:46)
https://github.com/sameersbn/docker-gitlab/issues/77
参见sameersbn的回答。
option 1: -v /etc/localtime:/etc/localtime:ro
option 2: -e "TZ=Asia/Shanghai"
答案 2 :(得分:44)
最简单的解决方案似乎是使用-v /etc/localtime:/etc/localtime:ro
选项运行容器。因此:
#run without tz info:
docker run --rm -t -i ubuntu date
Wed Apr 2 18:40:07 UTC 2014
# run with tz info:
docker run --rm -t -i -v /etc/localtime:/etc/localtime:ro ubuntu date
Wed Apr 2 11:40:29 PDT 2014
答案 3 :(得分:23)
在适用于Mac OS X Beta的Docker上,我在VM上遇到了很大的影响,它基于Alpine Linux。从example开始,您可以使用以下命令同步VM的时钟。
screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
但是,访问VM上的终端是另一个问题,如果使用screen命令可以执行此操作。
/dev/ttys003
该路径是一个符号链接,在我的系统上指向moby login
。
进入后,请注意root
只是#import "AppDelegate.h"
#import "InfosyncBaseViewController.h"
// Data submission.
#import "Record.h"
#import "ManagedObjectUtilities.h"
#import "RecordBO.h"
// Data sync.
#import "UserBO.h"
#import "FolderBO.h"
#import "SyncUtilities.h"
#import "FormBO.h"
#import "UserFolder.h"
#import "UserForm.h"
#import "ErrorMsgUtilities.h"
// Google Maps!
#import <GoogleMaps/GoogleMaps.h>
//Debugging
#define LOG_LEVEL_DEF ddLogLevel
#import <CocoaLumberjack/CocoaLumberjack.h>
//PushNotification Firebase
@import Firebase;
@import FirebaseMessaging;
@import FirebaseInstanceID;
@interface AppDelegate ()
{
NSString *InstanceID;
}
@property (nonatomic, strong) NSString *strUUID;
@property (nonatomic, strong) NSString *strDeviceToken;
@end
@implementation AppDelegate
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize id_forms = _id_forms;
@synthesize lastError = _lastError;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//push !!
// Register for remote notifications
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
// iOS 7.1 or earlier
UIRemoteNotificationType allNotificationTypes =(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound);
[application registerForRemoteNotificationTypes:allNotificationTypes];
} else {
// iOS 8 or later
// [END_EXCLUDE]
UIUserNotificationType allNotificationTypes = (UIRemoteNotificationTypeNewsstandContentAvailability|
UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
// [START configure_firebase]
[FIRApp configure];
// [END configure_firebase]
// Add observer for InstanceID token refresh callback.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshNotification:)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
// Override point for customization after application launch.
InfosyncBaseViewController *loginController = (InfosyncBaseViewController*)self.window.rootViewController;
loginController.managedObjectContext = self.managedObjectContext;
[GMSServices provideAPIKey:GOOGLE_MAPS_API_KEY];
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
#ifdef __IPHONE_8_0
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert
| UIUserNotificationTypeBadge
| UIUserNotificationTypeSound) categories:nil];
[application registerUserNotificationSettings:settings];
#endif
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
- (void)registerUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
DebugLog(@"push notif");
}
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(@"########### Received Background Fetch ###########");
//Download the Content .
//Cleanup
completionHandler(UIBackgroundFetchResultNewData);
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
[[AFNetworkReachabilityManager sharedManager] stopMonitoring];
[[EDQueue sharedInstance] stop];
#ifdef DEBUG_MODE
#ifdef ENABLE_UIVIEWSHOWALIGNMENTRECTS_SETTING
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"UIViewShowAlignmentRects"];
#endif // ENABLE_UIVIEWSHOWALIGNMENTRECTS_SETTING
#endif // DEBUG_MODE
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[[FIRMessaging messaging] disconnect];
NSLog(@"Disconnected from FCM");
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
//application.applicationIconBadgeNumber = 0;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
//application.applicationIconBadgeNumber = 0;
[self connectToFcm];
[[EDQueue sharedInstance] setDelegate:self];
[[EDQueue sharedInstance] start];
// Starting to monitor that we can reach the Internet.
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
// Edge / 3g / 4g available.
if (![AFNetworkReachabilityManager sharedManager].isReachableViaWiFi) {
// WiFi not available!
// Checking if celullar transmission is allowed.
User *loggedInUser = [UserBO loggedInUser];
if (![loggedInUser.syncOver3g boolValue]) {
// Syncing over celullar not allowed.
// Cancelling queue.
[[EDQueue sharedInstance] empty];
}
}
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
// WiFi available. Not doing anything. Connections will jump to WiFi.
break;
case AFNetworkReachabilityStatusNotReachable:
default:
// This will fail on whatever connections we had set up.
break;
}
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
#ifdef DEBUG_MODE
#ifdef ENABLE_UIVIEWSHOWALIGNMENTRECTS_SETTING
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"UIViewShowAlignmentRects"];
#endif // ENABLE_UIVIEWSHOWALIGNMENTRECTS_SETTING
#endif // DEBUG_MODE
}
//Push Messages test?
// [START receive_message]
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID.
NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);
// Pring full message.
NSLog(@"%@", userInfo);
//Success
completionHandler(UIBackgroundFetchResultNewData);
}
// [END receive_message]
// [START refresh_token]
- (void)tokenRefreshNotification:(NSNotification *)notification {
// Note that this callback will be fired everytime a new token is generated, including the first
// time. So if you need to retrieve the token as soon as it is available this is where that
// should be done.
NSString *refreshedToken = [[FIRInstanceID instanceID] token];
NSLog(@"InstanceID token: %@", refreshedToken);
// Connect to FCM since connection may have failed when attempted before having a token.
[self connectToFcm];
// TODO: If necessary send token to appliation server.
}
// [END refresh_token]
// [START connect_to_fcm]
- (void)connectToFcm {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Unable to connect to FCM. %@", error);
} else {
NSLog(@"Connected to FCM.");
}
}];
}
//push
// system push notification registration success callback, delegate to pushManager
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[[FIRInstanceID instanceID] setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeProd];
//push//NSLog(@"deviceToken1 = %@",deviceToken);
[application registerForRemoteNotifications];
}
// system push notification registration error callback, delegate to pushManager
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
//[[PushNotificationManager pushManager] handlePushRegistrationFailure:error];
}
// system push notifications callback, delegate to pushManager
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//[[PushNotificationManager pushManager] handlePushReceived:userInfo];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
if (application.applicationState == UIApplicationStateActive) {
if ([notification.alertBody isEqualToString:@""]) {
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"companyName", @"InfoSync")
message:notification.alertBody
delegate:self
cancelButtonTitle:NSLocalizedString(@"Ok", @"Aceptar")
otherButtonTitles:nil];
[alert show];
}
}else if (application.applicationState != UIApplicationStateActive){
// For present a specific controller after localNotification
// Ref.: https://hellomihai.wordpress.com/2015/02/26/opening-a-view-when-app-is-launched-from-a-local-notification-ios7-ios8/
// For now lost menu fuctionality
// if (application.applicationState != UIApplicationStateActive) { // only if not active
// UIViewController *myDesiredView = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"Whatever id from storyboard"];
// [self.window.rootViewController showViewController:myDesiredView sender:self];
//
// }
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"companyName", @"InfoSync")
message:NSLocalizedString(@"Your information no sent. Please try again in completed records.",@"No se pudo enviar la información. Favor de reintentar desde la pestaña de Registros completados")
delegate:self cancelButtonTitle:NSLocalizedString(@"Ok", @"Aceptar")
otherButtonTitles:nil];
[alert show];
}
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
}
-(void)sendNotification:(NSString*)notificationAlertBody
{
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [ NSDate dateWithTimeIntervalSinceNow:5];
localNotification.alertBody = notificationAlertBody;
localNotification.alertAction = NSLocalizedString(@"companyName", @"InfoSync");
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
@end
,没有密码。完成后,CTRL-A,D将断开与屏幕会话的连接。
注意:这曾经记录在Alpine Linux FAQ上,但似乎已被删除。我很幸运能够在2016年的Dockercon上展示它。看来Docker正试图完全从经验中抽象出VM,这就解释了为什么它不再被记录下来了。
答案 4 :(得分:1)
目前解码器上的osx时间漂移解决方案(2018年4月):
我确实在NTP服务器上安装了我的mac,但这个固定的时钟漂移带有容器:
来自https://docs.docker.com/docker-for-mac/troubleshoot/#known-issues:
如果您的系统无权访问NTP服务器,则在休眠后,Docker for Mac看到的时间可能与主机完全不同步。此外,在使用期间,时间可能会慢慢地不同步。要在休眠后手动重置时间,请运行:
docker run --rm --privileged alpine hwclock -s
或者,要解决这两个问题,您可以将本地时钟添加为主机的低优先级(高层)后备NTP时间源。为此,请编辑主机的/etc/ntp-restrict.conf以添加:
server 127.127.1.1 # LCL, local clock
fudge 127.127.1.1 stratum 12 # increase stratum
然后使用以下命令重新启动NTP服务
sudo launchctl unload /System/Library/LaunchDaemons/org.ntp.ntpd.plist
sudo launchctl load /System/Library/LaunchDaemons/org.ntp.ntpd.plist
答案 5 :(得分:0)
答案 6 :(得分:0)
如果您更喜欢TZ
解决方案,那么尽管您要求使用自己的时区(目前是11:09 CDT),但您可能会惊讶地看到显示了UTC时间:
$ docker run --rm -it -e "TZ=America/Chicago" ubuntu date
Mon Oct 26 16:09:04 America 2020
从实验上看,您似乎需要POSIX TZ
格式:
$ docker run --rm -it -e "TZ=CST6CDT" ubuntu date
Mon Oct 26 11:09:17 CDT 2020