1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class UnixDateTimeConvertor : DateTimeConverterBase { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return DateTime.Parse(reader.Value.ToString()); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { //System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //long timeStamp = (long)(((DateTime)value) - startTime).TotalMilliseconds; writer.WriteValue(((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss")); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服务 //GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter //{ // DateTimeFormat = "yyyy-MM-dd HH:mm:ss" //}); // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); //设置Datetime 到 時間戳 的互轉 JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings() { Formatting = Formatting.Indented, DateTimeZoneHandling = DateTimeZoneHandling.Local }; jSettings.Converters.Add(new UnixDateTimeConvertor()); config.Formatters.JsonFormatter.SerializerSettings = jSettings; } } |
from:https://www.cnblogs.com/liuqiyun/p/10729338.html
View Details一、创建.net core web api 的Demo 修改部分代码 端口随意指定,ip用星号“*”,方便接下来docker虚拟网络自动分配ip 下一步是Dockerfile文件,如果发现你的项目中没有此文件,很简单,右键项目=》添加=》Docker支持即可,然后修改文件如下图 然后发布项目并上传文件到服务器 二、将api项目部署到docker中 首先,进入到你上传的文件目录 根据目录下的Dockerfile创建镜像:docker build -t dockerapitestimage . (注意,注意,注意后面有一个点“.”,看清楚了,这个点表示当前目录上下文) 如果你在这一步失败了,请先尝试在docker下拉取dotnet镜像,执行命令 docker pull dotnet:latest ,拉取完之后再创建api镜像 这里要下载好几百兆的镜像包,网速太慢的话,建议尝试阿里云镜像加速,具体见我另外一篇文章 docker使用阿里云镜像加速 镜像创建成功后,我们就可以来创建容器并使用啦,继续往下 可以看到服务已经成功启动了,接下来准备访问一下试试 在linux中,首先我们输入$ docker ps 看下详情,如下图 发现我们的dockerapitest容器的ip地址是 0.0.0.0:8001,接着在linux中访问看看,成功了 linux下都没问题了,然后我们回windows下看看,如下图,显然成功了。 from:https://www.cnblogs.com/luoocean/p/11100684.html
View Details问题 模型验证无效时,没有进入到接口里,而是直接报400 Bad Request,非常不友好。 环境 SDK:.Net Core 2.2.401 开发工具:VS2017 step 1 创建接口
1 2 3 4 5 6 7 8 9 10 11 |
/// <summary> /// 注册 /// </summary> /// <param name="input">request Body</param> [HttpPost] [AllowAnonymous] public object PostRegister([FromBody] InputUserRegister input) { var userService = GetService<IUserService>(); return userService.Register(input); } |
Step 2 创建模型 引用命名空间
1 |
using System.ComponentModel.DataAnnotations; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class InputUserRegister { [Required(ErrorMessage = "请填写用户名")] [StringLength(20, ErrorMessage = "用户名长度过长")] public string UserName { get; set; } [Required(ErrorMessage = "请填写密码")] [StringLength(20, ErrorMessage = "密码长度过长")] public string Password { get; set; } [Required(ErrorMessage = "请填写确认密码")] [Compare("Password", ErrorMessage = "两次输入的密码不一致")] public string ConfirmPassword { get; set; } } |
Step 3 测试 解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#region 禁止默认行为 services.Configure<ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = (context) => { if (context.ModelState.IsValid) return null; var error = ""; foreach (var item in context.ModelState) { var state = item.Value; var message = state.Errors.FirstOrDefault(p => !string.IsNullOrWhiteSpace(p.ErrorMessage))?.ErrorMessage; if (string.IsNullOrWhiteSpace(message)) { message = state.Errors.FirstOrDefault(o => o.Exception != null)?.Exception.Message; } if (string.IsNullOrWhiteSpace(message)) continue; error = message; break; } return new JsonResult(new Models.VModels.ErrorResponse(error.ToString())); }; }); #endregion |
from:https://www.cnblogs.com/EminemJK/p/11498852.html
View Details客户端验证对用户向表单中输入的数据给出一个即时反馈。 服务器验证,主要是因为来自网络的信息都是不能信任的。 一、 为验证注解订单 1 、验证注解的使用,自定义错误提示消息 数据注解特性定义在 System.ComponentModel.DataAnnotations 中(但有一个特性不在这个命名空间),它提供了服务器端验证,当模型属性上使用这些特性时,框架也支持客户端验证。在命名空间DataAnnotations中,有4个特性可以用来应对一般验证场合。 (1)、字符非空,最大长度,值范围,两个属性相同,正则表达式 //字段非空,最大长度160 [Required(ErrorMessage="FirstName不能为空")] [StringLength(160, ErrorMessage = "FirstName太长了")] public string FirstName { get; set; } //正则表达式验证必须是电子邮件 [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage="邮件地址不正确")] public string Email { get; set; } //字段非空,数值类型最小值,最大值 [Required] [Range(typeof(decimal), "0.00", "49.99")] public decimal Total { get; set; } //对象两个属性拥有相同的值 [Compare("Email")] public string EmailConfirm { get; set; } […]
View Details一般的我们可以直接使用参数来接受,这个就不多介绍了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
[HttpGet] public IHttpActionResult Test2([FromUri]string name) { object obj = new { name = "sss", age = 78, sex = true }; return Ok(new { errcode = 0, data = obj }); } [HttpPost] public IHttpActionResult Test3([FromBody]string name) { throw new Exception("嘻嘻嘻"); } /// <summary> /// 返回强类型 /// </summary> /// <param name="name"></param> /// <returns></returns> [HttpGet] public CommonOutDto Test4([FromUri]string name) { CommonOutDto outDto = new CommonOutDto(); outDto.errcode = 0; return outDto; } |
现在一般使用json来传递参数,如果使用强类型,需要我们把类的属性和参数名设置一样就可以了。get,post都可以,这里只演示了post请求 ①使用参数名来接受,这样显示不管你是传递json字符串还是json对象都是接收不到的
1 2 3 4 5 |
[HttpPost] public IHttpActionResult Test4([FromBody]string json) { throw new Exception("嘻嘻嘻"); } |
②稍微改动下,把参数类型换成objct,这样我们不管是传递json对象和字符串都是能够接受到的
1 2 3 4 5 |
[HttpPost] public IHttpActionResult Test4([FromBody]object json) { throw new Exception("嘻嘻嘻"); } |
json对象; json字符串: 正解:普通的两种使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/// <summary> /// 如果没有定义Dto类型 /// </summary> /// <param name="json">json数据</param> /// <returns></returns> [HttpPost] public IHttpActionResult Test3([FromBody]object json) { JObject @object = JObject.Parse(json.ToString()); return Ok(@object); } /// <summary> /// 定义了Dto类型 /// </summary> /// <param name="inDto"> /// 根据json 定义的类 /// </param> /// <returns></returns> [HttpPost] public IHttpActionResult Test4(ToiletInfoInDto inDto) { // CommonOutDto 为自定义的返回类 CommonOutDto outDto = new CommonOutDto(); outDto.dataStr = "请求成功"; outDto.errcode = 0; return Ok(outDto); } |
1 |
ToiletInfoInDto : |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/// <summary> /// 厕所信息 /// </summary> public class ToiletInfoInDto { /// <summary> /// 厕所编号 /// </summary> public string CsNum { get; set; } /// <summary> /// 厕所名称 /// </summary> public string CsName { get; set; } /// <summary> /// 百度经度 /// </summary> public string CoordX { get; set; } /// <summary> /// 百度纬度 /// </summary> public string CoordY { get; set; } /// <summary> /// 厕所等级 /// </summary> public string Rank { get; set; } } |
1 |
CommonOutDto: |
1 2 3 4 5 6 7 8 9 10 11 |
/// <summary> /// 返回公共类 /// </summary> public class CommonOutDto { public int errcode { get; set; } public string dataStr { get; set; } public string errmsgStr { get; set; } } |
③mvc中也可以写接口,我们肯定使用过流接受过参数,那webapi中同样是可以的 mvc中可以直接写:
1 |
string json2 = new StreamReader(Request.InputStream).ReadToEnd(); |
webapi中没有 HttpContext这个,我们可以引用进行使用
1 2 |
//引用 using System.Web; string json2 = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd(); |
webapi中我们使用request强制同步获取数据,显示获取不到
1 2 |
//强制同步获取不到数据 string aa = this.Request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); |
推荐:使用异步的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
/// <summary> /// 使用objct接受 /// </summary> /// <param name="json"></param> /// <returns></returns> [HttpPost] public async Task<IHttpActionResult> TestAsync([FromBody]object json) { JObject @object = JObject.Parse(json.ToString()); return await Task.FromResult<IHttpActionResult>(Ok(@object)); } /// <summary> /// 使用强类型接受 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] public async Task<IHttpActionResult> TestAsync2(ToiletInfoInDto inDto) { return await Task.FromResult<IHttpActionResult>(Ok(inDto)); } /// <summary> /// 使用读取数据的方式 /// </summary> /// <returns></returns> [HttpPost] public async Task<IHttpActionResult> TestAsync3() { string aa = await this.Request.Content.ReadAsStringAsync(); return await Task.FromResult<IHttpActionResult>(Ok(aa)); } /// <summary> /// 使用强类型接受,返回强类型 推荐这种,输入,输出都新建一个对应的Dto进行处理 /// </summary> /// <param name="inDto">输入类</param> /// <returns>输出类</returns> [HttpPost] public async Task<CommonOutDto> TestAsync4(ToiletInfoInDto inDto) { CommonOutDto outDto = new CommonOutDto(); outDto.errcode = 0; return await Task.FromResult(outDto); } |
显示结果:
1 |
可以看到我们的 TestAsync2 接口中,我们的属性小写了,这是自己序列化json数据造成的,俗称:驼峰式。 当然这个是可以设置的,我们在webapiConfig.cs 中可以设置我们的json的属性 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服务 // Web API 路由 config.MapHttpAttributeRoutes(); //多添加一个action config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); // 干掉XML序列化器 两种都可以 //GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); config.Formatters.Remove(config.Formatters.XmlFormatter); //配置json数据格式 JsonMediaTypeFormatter jsonFormatter = config.Formatters.JsonFormatter; //忽略循环引用,如果设置为Error,则遇到循环引用的时候报错(建议设置为Error,这样更规范) jsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Error; //日期格式化,默认的格式也不好看 jsonFormatter.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 对 JSON 数据使用混合大小写。跟属性名同样的大小.输出 jsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver(); //json中属性开头字母小写的驼峰命名 //jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } } |
总结: 1:一般的我们使用Object类型或者强类型来接接收 2:提高效率,我们是异步 题外:我们一般都会准备一个Dto来接受我们的json对象,如果你不想这样写,也可以使用JObject来用。 from:https://www.cnblogs.com/Sea1ee/p/10438838.html
View Details本教程演示如何在 Docker 容器中运行 ASP.NET Core 应用。 在本教程中,你将了解: 了解 Microsoft.NET 核心 Docker 映像 下载 ASP.NET Core 示例应用 本地运行示例应用 在 Linux 容器中运行示例应用 在 Windows 容器中运行示例应用 手动生成和部署 ASP.NET Core Docker 映像 在本教程中,你下载 ASP.NET Core 示例应用并在 Docker 容器中运行它。 此示例适用于 Linux 和 Windows 容器。 示例 Dockerfile 使用 Docker 多阶段构建功能在不同的容器中生成和运行。 生成和运行容器是由 Microsoft 从 Docker 中心提供的映像中创建的: dotnet/core/sdk 此示例将此映像用于生成应用。 此映像包含带有命令行工具 (CLI) 的 .NET Core SDK。 此映像对本地开发、调试和单元测试进行了优化。 为开发和编译而安装的工具使其成为一个相对较大的映像。 dotnet/core/aspnet 此示例将此映像用于运行应用。 此映像包含 ASP.NET Core 运行时和库,并针对在生产中运行应用进行了优化。 此映像专为部署和应用启动的速度而设计,相对较小,因此优化了从 Docker 注册表到 Docker 主机的网络性能。 仅将运行应用所需的二进制文件和内容复制到容器。 已准备运行内容,以此实现从 Docker run 到应用启动的最快时间。 Docker 模型中不需要动态代码编译。 先决条件 .NET Core SDK 3.0 Docker 客户端 18.03 或更高版本 Linux 分布 CentOS Debian Fedora Ubuntu macOS Windows Git 下载示例应用 通过克隆 .NET Core Docker 存储库下载示例: 控制台复制 […]
View DetailsDocker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定。 譬如我要启动一个centos容器,宿主机的/test目录挂载到容器的/soft目录,可通过以下方式指定: # docker run -it -v /test:/soft centos /bin/bash 这样在容器启动后,容器内会自动创建/soft的目录。通过这种方式,我们可以明确一点,即-v参数中,冒号":"前面的目录是宿主机目录,后面的目录是容器内目录。 貌似简单,其实不然,下面我们来验证一下: 一、容器目录不可以为相对路径
1 2 3 |
[root@localhost ~]# docker run -it -v /test:soft centos /bin/bash invalid value "/test:soft" for flag -v: soft is not an absolute path See 'docker run --help'. |
直接报错,提示soft不是一个绝对路径,所谓的绝对路径,必须以下斜线“/”开头。 二、宿主机目录如果不存在,则会自动生成 如果宿主机中存在/test目录,首先删除它
1 2 3 |
[root@localhost ~]# rm -rf /test [root@localhost ~]# ls / bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var |
启动容器
1 2 3 |
[root@localhost ~]# docker run -it -v /test:/soft centos /bin/bash [root@a487a3ca7997 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin soft srv sys tmp usr var |
查看宿主机,发现新增了一个/test目录
1 2 |
[root@localhost ~]# ls / bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys test tmp usr var |
三、宿主机的目录如果为相对路径呢? 这次,我们换个目录名test1试试
1 |
# docker run -it -v test1:/soft centos /bin/bash |
再到宿主机上查看是否新增了一个/test1目录,结果没有,是不是因为我用的是相对路径,所以生成的test1目录在当前目录下,结果发现还是没有。那容器内的/soft目录挂载到哪里去了?通过docker inspect命令,查看容器“Mounts”那一部分,我们可以得到这个问题的答案。
1 2 3 4 5 6 7 8 9 10 |
"Mounts": [ { "Name": "test1", "Source": "/var/lib/docker/volumes/test1/_data", "Destination": "/soft", "Driver": "local", "Mode": "z", "RW": true } ], |
可以看出,容器内的/soft目录挂载的是宿主机上的/var/lib/docker/volumes/test1/_data目录 原来,所谓的相对路径指的是/var/lib/docker/volumes/,与宿主机的当前目录无关。 四、如果只是-v指定一个目录,这个又是如何对应呢? 启动一个容器
1 2 3 |
[root@localhost ~]# docker run -it -v /test2 centos /bin/bash [root@ea24067bc902 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys test2 tmp usr var |
同样使用docker inspect命令查看宿主机的挂载目录
1 2 3 4 5 6 7 8 9 10 |
"Mounts": [ { "Name": "96256232eb74edb139d652746f0fe426e57fbacdf73376963e3acdb411b3d73a", "Source": "/var/lib/docker/volumes/96256232eb74edb139d652746f0fe426e57fbacdf73376963e3acdb411b3d73a/_data", "Destination": "/test2", "Driver": "local", "Mode": "", "RW": true } ], |
可以看出,同3中的结果类似,只不过,它不是相对路径的目录名,而是随机生成的一个目录名。 五、如果在容器内修改了目录的属主和属组,那么对应的挂载点是否会修改呢? 首先开启一个容器,查看容器内/soft目录的属性
1 2 3 |
[root@localhost ~]# docker run -it -v /test:/soft centos /bin/bash [root@b5ed8216401f /]# ll -d /soft/ drwxr-xr-x 2 root root 6 Sep 24 03:48 /soft/ |
查看宿主机内/test目录的属性
1 2 |
[root@localhost ~]# ll -d /test/ drwxr-xr-x 2 root root 6 Sep 24 11:48 /test/ |
在容器内新建用户,修改/soft的属主和属组
1 2 3 4 |
[root@b5ed8216401f /]# useradd victor [root@b5ed8216401f /]# chown -R victor.victor /soft/ [root@b5ed8216401f /]# ll -d /soft/ drwxr-xr-x 2 victor victor 6 Sep 24 03:48 /soft/ |
再来看看宿主机内/test目录的属主和属组是否会发生变化?
1 2 |
[root@localhost ~]# ll -d /test/ drwxr-xr-x 2 mycat mycat 6 Sep 24 11:48 /test/ |
竟然变为mycat了。。。 原来,这个与UID有关系,UID,即“用户标识号”,是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。 首先查看容器内victor对应的UID是多少,
1 2 |
[root@b5ed8216401f /]# cat /etc/passwd | grep victor victor:x:1000:1000::/home/victor:/bin/bash |
victor的UID为1000,那么宿主机内1000对应的用户是谁呢?
1 2 |
[root@localhost ~]# cat /etc/passwd |grep 1000 mycat:x:1000:1000::/home/mycat:/bin/bash |
可以看出,宿主机内UID 1000对应的用户是mycat。 六、容器销毁了,在宿主机上新建的挂载目录是否会消失? 在这里,主要验证两种情况:一、指定了宿主机目录,即 -v /test:/soft。二、没有指定宿主机目录,即-v /soft 第一种情况:
1 2 3 4 5 6 7 8 9 10 |
[root@localhost ~]# rm -rf /test --首先删除宿主机的/test目录 [root@localhost ~]# ls / --可以看到,宿主机上无/test目录 bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var [root@localhost ~]# docker run -it --name=centos_test -v /test:/soft centos /bin/bash --启动容器,为了删除方便,我用--name参数指定了容器的名字 [root@82ad7f3a779a /]# exit exit [root@localhost ~]# docker rm centos_test --删除容器 centos_test [root@localhost ~]# ls / --发现 /test目录依旧存在 bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys test tmp usr var |
可以看出,即便容器销毁了,新建的挂载目录不会消失。进一步也可验证,如果宿主机目录的属主和属组发生了变化,容器销毁后,宿主机目录的属主和属组不会恢复到挂载之前的状态。 第二种情况,通过上面的验证知道,如果没有指定宿主机的目录,则容器会在/var/lib/docker/volumes/随机配置一个目录,那么我们看看这种情况下的容器销毁是否会导致相应目录的删除 首先启动容器
1 2 3 |
[root@localhost ~]# docker run -it --name=centos_test -v /soft centos /bin/bash [root@6b75579ec934 /]# exit exit |
通过docker inspect命令查看容器在宿主机上生成的挂载目录
1 2 3 4 5 6 7 8 9 10 |
"Mounts": [ { "Name": "b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301", "Source": "/var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301/_data", "Destination": "/soft", "Driver": "local", "Mode": "", "RW": true } ], |
对应的是/var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301/_data目录 销毁容器,看目录是否存在
1 2 3 4 5 |
[root@localhost ~]# docker rm centos_test centos_test [root@localhost ~]# ll /var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301 total 0 drwxr-xr-x 2 root root 6 Sep 24 14:25 _data |
发现该目录依旧存在,即便重启了docker服务,该目录依旧存在
1 2 3 4 |
[root@localhost ~]# systemctl restart docker [root@localhost ~]# ll /var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301 total 0 drwxr-xr-x 2 root root 6 Sep 24 14:25 _data |
七、挂载宿主机已存在目录后,在容器内对其进行操作,报“Permission denied”。 可通过两种方式解决: 1> 关闭selinux。 临时关闭:# setenforce 0 永久关闭:修改/etc/sysconfig/selinux文件,将SELINUX的值设置为disabled。 2> 以特权方式启动容器 指定--privileged参数 如:# docker run -it --privileged=true -v […]
View Details1、Docker导入本地镜像 有时候我们自己在本地或者其它小伙伴电脑上拷贝了一份镜像,有了这个镜像之后,我们可以把本地的镜像导入,使用docker import 命令。 例如这里下载了一个 alibaba-rocketmq-3.2.6.tar.gz 镜像文件,使用下列命令导入:
1 2 3 4 5 6 7 8 |
[root@rocketmq-nameserver4 dev]# <strong>cat alibaba-rocketmq-3.2.6.tar.gz | docker import - rocketmq:3.2.6</strong>(镜像名自己定义) [root@rocketmq-nameserver4 dev]#<strong> docker images</strong> REPOSITORY TAG IMAGE ID CREATED SIZE rocketmq 3.2.6 53925d1cf9f0 23 seconds ago 14MB my/python v1 36b6e288656c 2 days ago 281MB my/centos_width_python v1.0.1 36b6e288656c 2 days ago 281MB my/sinatra v2 8ba1d6a3ce4e 2 days ago 453MB hello-world latest 725dcfab7d63 4 months ago 1.84kB |
可以看到导入完成后,docker为我们生成了一个镜像ID,使用docker images也可以看到我们刚刚从本地导入的镜像。 注意镜像文件必须是tar.gz类型的文件。 [root@rocketmq-nameserver4 dev]# docker run -it rocketmq:3.2.6 /bin/bash ##启动导入本地镜像,会报如下异常 docker: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory". 解决方案: 暂时无解,有知道的兄台请在下面留言,在此先谢了。 2、保存镜像 我们的镜像做好之后,我们要保存起来,以供备份使用,该怎么做?使用docker save命令,保存镜像到本地。
1 2 |
[root@rocketmq-nameserver4 dev]# docker save -o rocketmq.tar rocketmq ##-o:指定保存的镜像的名字;rocketmq.tar:保存到本地的镜像名称;rocketmq:镜像名字,通过"docker images"查看 [root@rocketmq-nameserver4 dev]# ll |
rocketmq.tar为刚保存的镜像 3、载入镜像 我们有了本地的镜像文件,在需要的时候可以使用docker load将本地保存的镜像再次导入docker中。 docker load --input rocketmq.tar 或 docker load < rocketmq.tar 4、删除镜像 有些镜像过时了,我们需要删除。使用如下的命令:docker rmi -f image_id ##-f:表示强制删除镜像;image_id:镜像id from:https://www.cnblogs.com/linjiqin/p/8604756.html
View Details
1 2 3 4 5 6 |
========== 正在准备容器 ========== 正在准备 Docker 容器... C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -NoProfile -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File "C:\Users\MESTC\AppData\Local\Temp\GetVsDbg.ps1" -Version vs2017u5 -RuntimeID linux-x64 -InstallPath "C:\Users\MESTC\vsdbg\vs2017u5" Info: Using vsdbg version '16.0.20412.1' Info: Using Runtime ID 'linux-x64' Info: C:\Users\MESTC\vsdbg\vs2017u5 exists, deleting. |
如上情况 感兴趣可以打开 GetVsDbg.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# Copyright (c) Microsoft. All rights reserved. <# .SYNOPSIS Downloads the given $Version of vsdbg for the given $RuntimeID and installs it to the given $InstallPath .DESCRIPTION The following script will download vsdbg and install vsdbg, the .NET Core Debugger .PARAMETER Version Specifies the version of vsdbg to install. Can be 'latest', 'vs2019', 'vs2017u5', 'vs2017u1', or a specific version string i.e. 15.0.25930.0 .PARAMETER RuntimeID Specifies the .NET Runtime ID of the vsdbg that will be downloaded. Example: linux-x64. Defaults to win7-x64. .Parameter InstallPath Specifies the path where vsdbg will be installed. Defaults to the directory containing this script. .INPUTS None. You cannot pipe inputs to GetVsDbg. .EXAMPLE C:\PS> .\GetVsDbg.ps1 -Version latest -RuntimeID linux-x64 -InstallPath .\vsdbg .LINK For more information about using this script with Visual Studio Code see: https://github.com/OmniSharp/omnisharp-vscode/wiki/Attaching-to-remote-processes For more information about using this script with Visual Studio see: https://github.com/Microsoft/MIEngine/wiki/Offroad-Debugging-of-.NET-Core-on-Linux---OSX-from-Visual-Studio To report issues, see: https://github.com/omnisharp/omnisharp-vscode/issues #> Param ( [Parameter(Mandatory=$true, ParameterSetName="ByName")] [string] [ValidateSet("latest", "vs2019", "vs2017u1", "vs2017u5")] $Version, [Parameter(Mandatory=$true, ParameterSetName="ByNumber")] [string] [ValidatePattern("\d+\.\d+\.\d+.*")] $VersionNumber, [Parameter(Mandatory=$false)] [string] $RuntimeID, [Parameter(Mandatory=$false)] [string] $InstallPath = (Split-Path -Path $MyInvocation.MyCommand.Definition) ) $ErrorActionPreference="Stop" # In a separate method to prevent locking zip files. function DownloadAndExtract([string]$url, [string]$targetLocation) { Add-Type -assembly "System.IO.Compression.FileSystem" Add-Type -assembly "System.IO.Compression" [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Try { $zipStream = (New-Object System.Net.WebClient).OpenRead($url) } Catch { Write-Host "Info: Opening stream failed, trying again with proxy settings." $proxy = [System.Net.WebRequest]::GetSystemWebProxy() $proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials $webClient = New-Object System.Net.WebClient $webClient.UseDefaultCredentials = $false $webClient.proxy = $proxy $zipStream = $webClient.OpenRead($url) } $zipArchive = New-Object System.IO.Compression.ZipArchive -ArgumentList $zipStream [System.IO.Compression.ZipFileExtensions]::ExtractToDirectory($zipArchive, $targetLocation) $zipArchive.Dispose() $zipStream.Dispose() } # Checks if the existing version is the latest version. function IsLatest([string]$installationPath, [string]$runtimeId, [string]$version) { $SuccessRidFile = Join-Path -Path $installationPath -ChildPath "success_rid.txt" if (Test-Path $SuccessRidFile) { $LastRid = Get-Content -Path $SuccessRidFile if ($LastRid -ne $runtimeId) { return $false } } else { return $false } $SuccessVersionFile = Join-Path -Path $installationPath -ChildPath "success_version.txt" if (Test-Path $SuccessVersionFile) { $LastVersion = Get-Content -Path $SuccessVersionFile if ($LastVersion -ne $version) { return $false } } else { return $false } return $true } function WriteSuccessInfo([string]$installationPath, [string]$runtimeId, [string]$version) { $SuccessRidFile = Join-Path -Path $installationPath -ChildPath "success_rid.txt" $runtimeId | Out-File -Encoding utf8 $SuccessRidFile $SuccessVersionFile = Join-Path -Path $installationPath -ChildPath "success_version.txt" $version | Out-File -Encoding utf8 $SuccessVersionFile } $ExplitVersionNumberUsed = $false if ($Version -eq "latest") { $VersionNumber = "16.0.20412.1" } elseif ($Version -eq "vs2019") { $VersionNumber = "16.0.20412.1" } elseif ($Version -eq "vs2017u5") { $VersionNumber = "16.0.20412.1" } elseif ($Version -eq "vs2017u1") { $VersionNumber = "15.1.10630.1" } else { $ExplitVersionNumberUsed = $true } Write-Host "Info: Using vsdbg version '$VersionNumber'" if (-not $RuntimeID) { $RuntimeID = "win7-x64" } elseif (-not $ExplitVersionNumberUsed) { $legacyLinuxRuntimeIds = @{ "debian.8-x64" = ""; "rhel.7.2-x64" = ""; "centos.7-x64" = ""; "fedora.23-x64" = ""; "opensuse.13.2-x64" = ""; "ubuntu.14.04-x64" = ""; "ubuntu.16.04-x64" = ""; "ubuntu.16.10-x64" = ""; "fedora.24-x64" = ""; "opensuse.42.1-x64" = ""; } # Remap the old distro-specific runtime ids unless the caller specified an exact build number. # We don't do this in the exact build number case so that old builds can be used. if ($legacyLinuxRuntimeIds.ContainsKey($RuntimeID.ToLowerInvariant())) { $RuntimeID = "linux-x64" } } Write-Host "Info: Using Runtime ID '$RuntimeID'" # if we were given a relative path, assume its relative to the script directory and create an absolute path if (-not([System.IO.Path]::IsPathRooted($InstallPath))) { $InstallPath = Join-Path -Path (Split-Path -Path $MyInvocation.MyCommand.Definition) -ChildPath $InstallPath } if (IsLatest $InstallPath $RuntimeID $VersionNumber) { Write-Host "Info: Latest version of VsDbg is present. Skipping downloads" } else { if (Test-Path $InstallPath) { Write-Host "Info: $InstallPath exists, deleting." Remove-Item $InstallPath -Force -Recurse -ErrorAction Stop } $target = ("vsdbg-" + $VersionNumber).Replace('.','-') + "/vsdbg-" + $RuntimeID + ".zip" $url = "https://vsdebugger.azureedge.net/" + $target DownloadAndExtract $url $InstallPath WriteSuccessInfo $InstallPath $RuntimeID $VersionNumber Write-Host "Info: Successfully installed vsdbg at '$InstallPath'" } |
1 2 3 4 5 6 |
========== 正在准备容器 ========== 正在准备 Docker 容器... C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -NoProfile -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File "C:\Users\MESTC\AppData\Local\Temp\GetVsDbg.ps1" -Version vs2017u5 -RuntimeID linux-x64 -InstallPath "C:\Users\MESTC\vsdbg\vs2017u5" Info: Using vsdbg version '16.0.20412.1' Info: Using Runtime ID 'linux-x64' Info: C:\Users\MESTC\vsdbg\vs2017u5 exists, deleting. |
下面说说解决方案 下载包
1 |
https://vsdebugger.azureedge.net/vsdbg-(你的版本号.号换成-号)/vsdbg-(你的Runtime ID).zip |
1 |
例如我的 |
1 2 3 |
https://vsdebugger.azureedge.net/vsdbg-16-0-20412-1/vsdbg-linux-x64.zip 下载之后解压到你的安装路径 例如我的 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
-InstallPath "C:\Users\MESTC\vsdbg\vs2017u5" 然后在该文件下添加一个<em>success_rid.txt文件,内容为</em>你的Runtime ID 例如我的linux-x64 还要添加一个success_version.txt文件,内容为你的版本号,如16.0.20412.1 重启 visual studio 下面还会下载另一个,相同的处理方式,再重启一次就ok了 最新版操作过程 最新下载文件路径 https://vsdebugger.azureedge.net/vsdbg-16-2-10709-2/vsdbg-linux-x64.zip https://vsdebugger.azureedge.net/vsdbg-16-2-10709-2/vsdbg-linux-musl-x64.zip 解压路径 |
1 |
C:\Users\用户名\vsdbg\vs2017u5 -> vsdbg-linux-x64.zip |
1 2 3 4 |
C:\Users\用户名\vsdbg\vs2017u5\linux-musl-x64 -> vsdbg-linux-musl-x64.zip 解压完了,在路径 C:\Users\用户名\vsdbg\vs2017u5 里面 新建 <em>success_rid.txt 编辑内容 </em>linux-x64,再新建 success_version.txt <em>编辑内容 16.2.10709.2 </em> |
1 |
在路径 C:\Users\用户名\vsdbg\vs2017u5\linux-musl-x64 里面 新建 <em>success_rid.txt 编辑内容 </em>linux-musl-x64,再新建 success_version.txt <em>编辑内容 16.2.10709.2<br>完成</em> |
转载于:https://www.cnblogs.com/microestc/p/10784877.html from:https://blog.csdn.net/weixin_30809333/article/details/99176681
View Details工具VS2019 MSDN解决方法:https://docs.microsoft.com/zh-cn/visualstudio/containers/troubleshooting-docker-errors?view=vs-2019 执行net localgroup docker-users DOMAIN\username(“DOMAIN\username”这个是用户名,根据你的电脑的用户名填入) /add from:https://blog.csdn.net/weixin_41432198/article/details/104575932
View Details